From 510cb8524159a23a32a33be81d49f55a40526a5e Mon Sep 17 00:00:00 2001 From: kgv Date: Wed, 8 Nov 2017 15:25:51 +0300 Subject: [PATCH] 0029302: Foundation Classes, NCollection - optimize iteration of indexed maps NCollection_IndexedMap and NCollection_IndexedDataMap now access Key by Index number without computing Hash code. IndexedMapNode::myNext2 and IndexedDataMapNode::myNext2 fields have been removed, so that indexed map now may utilize less memory. TCollection::NextPrimeForMap() has been extended upto 2038431745 (almost full signed 32-bit integer range), and NCollection_BaseMap::mySaturated property has been removed. NCollection_IndexedDataMap::RemoveFromIndex(), FindKey(), FindFromIndex(), ChangeFromIndex() - removed duplicating checks for out of range input. --- src/NCollection/NCollection_BaseMap.cxx | 7 +- src/NCollection/NCollection_BaseMap.hxx | 19 +- .../NCollection_IndexedDataMap.hxx | 289 ++++++------------ src/NCollection/NCollection_IndexedMap.hxx | 226 +++++--------- src/TCollection/TCollection.cxx | 63 ++-- 5 files changed, 225 insertions(+), 379 deletions(-) diff --git a/src/NCollection/NCollection_BaseMap.cxx b/src/NCollection/NCollection_BaseMap.cxx index 71c499d1d1..7001ae5950 100644 --- a/src/NCollection/NCollection_BaseMap.cxx +++ b/src/NCollection/NCollection_BaseMap.cxx @@ -29,7 +29,6 @@ Standard_Boolean NCollection_BaseMap::BeginResize NCollection_ListNode**& data1, NCollection_ListNode**& data2) const { - if (mySaturated) return Standard_False; N = NextPrimeForMap(NbBuckets); if (N <= myNbBuckets) { if (!myData1) @@ -57,17 +56,17 @@ Standard_Boolean NCollection_BaseMap::BeginResize //======================================================================= void NCollection_BaseMap::EndResize - (const Standard_Integer NbBuckets, + (const Standard_Integer theNbBuckets, const Standard_Integer N, NCollection_ListNode** data1, NCollection_ListNode** data2) { + (void )theNbBuckets; // obsolete parameter if (myData1) myAllocator->Free(myData1); if (myData2) myAllocator->Free(myData2); myNbBuckets = N; - mySaturated = (myNbBuckets <= NbBuckets); myData1 = data1; myData2 = data2; } @@ -105,7 +104,6 @@ void NCollection_BaseMap::Destroy (NCollection_DelMapNode fDel, mySize = 0; if (doReleaseMemory) { - mySaturated = Standard_False; if (myData1) myAllocator->Free(myData1); if (isDouble && myData2) @@ -124,7 +122,6 @@ void NCollection_BaseMap::Statistics(Standard_OStream& S) const { S <<"\nMap Statistics\n---------------\n\n"; S <<"This Map has "< myNbBuckets)); } + { return IsEmpty() || (mySize > myNbBuckets); } //! Increment - void Increment() - { mySize++; } + Standard_Integer Increment() { return ++mySize; } //! Decrement - void Decrement() - { mySize--; } + Standard_Integer Decrement() { return --mySize; } //! Destroy Standard_EXPORT void Destroy(NCollection_DelMapNode fDel, @@ -213,10 +210,9 @@ public: std::swap (myAllocator, theOther.myAllocator); std::swap (myData1, theOther.myData1); std::swap (myData2, theOther.myData2); - //std::swap (isDouble, theOther.isDouble); - std::swap (mySaturated, theOther.mySaturated); std::swap (myNbBuckets, theOther.myNbBuckets); std::swap (mySize, theOther.mySize); + //std::swap (isDouble, theOther.isDouble); } protected: @@ -227,10 +223,9 @@ public: private: // ---------- PRIVATE FIELDS ------------ - Standard_Boolean isDouble; - Standard_Boolean mySaturated; Standard_Integer myNbBuckets; Standard_Integer mySize; + Standard_Boolean isDouble; // ---------- FRIEND CLASSES ------------ friend class Iterator; diff --git a/src/NCollection/NCollection_IndexedDataMap.hxx b/src/NCollection/NCollection_IndexedDataMap.hxx index 6b8574fefe..da2c6856f1 100644 --- a/src/NCollection/NCollection_IndexedDataMap.hxx +++ b/src/NCollection/NCollection_IndexedDataMap.hxx @@ -62,26 +62,19 @@ private: public: //! Constructor with 'Next' IndexedDataMapNode (const TheKeyType& theKey1, - const Standard_Integer theKey2, + const Standard_Integer theIndex, const TheItemType& theItem, - NCollection_ListNode* theNext1, - NCollection_ListNode* theNext2) : - NCollection_TListNode(theItem,theNext1), - myKey1(theKey1), - myKey2(theKey2), - myNext2((IndexedDataMapNode*)theNext2) + NCollection_ListNode* theNext1) + : NCollection_TListNode(theItem,theNext1), + myKey1 (theKey1), + myIndex (theIndex) { } //! Key1 - TheKeyType& Key1 (void) - { return myKey1; } - //! Key2 - Standard_Integer& Key2 (void) - { return myKey2; } - //! Next2 - IndexedDataMapNode*& Next2 (void) - { return myNext2; } - + TheKeyType& Key1() { return myKey1; } + //! Index + Standard_Integer& Index() { return myIndex; } + //! Static deleter to be passed to BaseList static void delNode (NCollection_ListNode * theNode, Handle(NCollection_BaseAllocator)& theAl) @@ -90,9 +83,8 @@ private: theAl->Free(theNode); } private: - TheKeyType myKey1; - Standard_Integer myKey2; - IndexedDataMapNode * myNext2; + TheKeyType myKey1; + Standard_Integer myIndex; }; public: @@ -101,13 +93,14 @@ private: { public: //! Empty constructor - Iterator (void) : - myMap(NULL), - myIndex(0) {} + Iterator() + : myMap (NULL), + myNode (NULL), + myIndex (0) {} //! Constructor Iterator (const NCollection_IndexedDataMap& theMap) : myMap ((NCollection_IndexedDataMap* )&theMap), - myNode (myMap->nodeFromIndex (1)), + myNode (!theMap.IsEmpty() ? (IndexedDataMapNode* )myMap->myData2[0] : NULL), myIndex (1) {} //! Query if the end of collection is reached by iterator Standard_Boolean More(void) const @@ -115,7 +108,7 @@ private: //! Make a step along the collection void Next(void) { - myNode = myMap->nodeFromIndex (++myIndex); + myNode = (IndexedDataMapNode* )myMap->myData2[++myIndex - 1]; } //! Value access const TheItemType& Value(void) const @@ -195,18 +188,14 @@ private: Clear(); ReSize (theOther.Extent()-1); - Standard_Integer i; - for (i=1; i<=theOther.Extent(); i++) + for (Standard_Integer anIndexIter = 1; anIndexIter <= theOther.Extent(); ++anIndexIter) { - TheKeyType aKey1 = theOther.FindKey(i); - TheItemType anItem = theOther.FindFromIndex(i); - Standard_Integer iK1 = Hasher::HashCode (aKey1, NbBuckets()); - Standard_Integer iK2 = ::HashCode (i, NbBuckets()); - IndexedDataMapNode * pNode = - new (this->myAllocator) IndexedDataMapNode (aKey1, i, anItem, - myData1[iK1], myData2[iK2]); - myData1[iK1] = pNode; - myData2[iK2] = pNode; + const TheKeyType& aKey1 = theOther.FindKey (anIndexIter); + const TheItemType& anItem = theOther.FindFromIndex(anIndexIter); + const Standard_Integer iK1 = Hasher::HashCode (aKey1, NbBuckets()); + IndexedDataMapNode* pNode = new (this->myAllocator) IndexedDataMapNode (aKey1, anIndexIter, anItem, myData1[iK1]); + myData1[iK1] = pNode; + myData2[anIndexIter - 1] = pNode; Increment(); } return *this; @@ -228,22 +217,18 @@ private: { if (myData1) { - IndexedDataMapNode *p, *q; - Standard_Integer i, iK1, iK2; - for (i = 0; i <= NbBuckets(); i++) + memcpy (ppNewData2, myData2, sizeof(IndexedDataMapNode*) * Extent()); + for (Standard_Integer aBucketIter = 0; aBucketIter <= NbBuckets(); ++aBucketIter) { - if (myData1[i]) + if (myData1[aBucketIter]) { - p = (IndexedDataMapNode *) myData1[i]; + IndexedDataMapNode* p = (IndexedDataMapNode *) myData1[aBucketIter]; while (p) { - iK1 = Hasher::HashCode (p->Key1(), newBuck); - iK2 = ::HashCode (p->Key2(), newBuck); - q = (IndexedDataMapNode*) p->Next(); - p->Next() = ppNewData1[iK1]; - p->Next2() = (IndexedDataMapNode*)ppNewData2[iK2]; + const Standard_Integer iK1 = Hasher::HashCode (p->Key1(), newBuck); + IndexedDataMapNode* q = (IndexedDataMapNode* )p->Next(); + p->Next() = ppNewData1[iK1]; ppNewData1[iK1] = p; - ppNewData2[iK2] = p; p = q; } } @@ -256,24 +241,27 @@ private: //! Add Standard_Integer Add (const TheKeyType& theKey1, const TheItemType& theItem) { - if (Resizable()) + if (Resizable()) + { ReSize(Extent()); - Standard_Integer iK1 = Hasher::HashCode (theKey1, NbBuckets()); - IndexedDataMapNode * pNode; - pNode = (IndexedDataMapNode *) myData1[iK1]; + } + + const Standard_Integer iK1 = Hasher::HashCode (theKey1, NbBuckets()); + IndexedDataMapNode* pNode = (IndexedDataMapNode* )myData1[iK1]; while (pNode) { if (Hasher::IsEqual (pNode->Key1(), theKey1)) - return pNode->Key2(); + { + return pNode->Index(); + } pNode = (IndexedDataMapNode *) pNode->Next(); } - Increment(); - Standard_Integer iK2 = ::HashCode(Extent(),NbBuckets()); - pNode = new (this->myAllocator) IndexedDataMapNode (theKey1, Extent(), theItem, - myData1[iK1], myData2[iK2]); - myData1[iK1] = pNode; - myData2[iK2] = pNode; - return Extent(); + + const Standard_Integer aNewIndex = Increment(); + pNode = new (this->myAllocator) IndexedDataMapNode (theKey1, aNewIndex, theItem, myData1[iK1]); + myData1[iK1] = pNode; + myData2[aNewIndex - 1] = pNode; + return aNewIndex; } //! Contains @@ -302,15 +290,14 @@ private: "NCollection_IndexedDataMap::Substitute : " "Index is out of range"); - IndexedDataMapNode * p; // check if theKey1 is not already in the map - Standard_Integer iK1 = Hasher::HashCode (theKey1, NbBuckets()); - p = (IndexedDataMapNode *) myData1[iK1]; + const Standard_Integer iK1 = Hasher::HashCode (theKey1, NbBuckets()); + IndexedDataMapNode* p = (IndexedDataMapNode *) myData1[iK1]; while (p) { if (Hasher::IsEqual (p->Key1(), theKey1)) { - if (p->Key2() != theIndex) + if (p->Index() != theIndex) { throw Standard_DomainError ("NCollection_IndexedDataMap::Substitute : " "Attempt to substitute existing key"); @@ -323,17 +310,10 @@ private: } // Find the node for the index I - Standard_Integer iK2 = ::HashCode (theIndex, NbBuckets()); - p = (IndexedDataMapNode *) myData2[iK2]; - while (p) - { - if (p->Key2() == theIndex) - break; - p = (IndexedDataMapNode*) p->Next2(); - } + p = (IndexedDataMapNode* )myData2[theIndex - 1]; // remove the old key - Standard_Integer iK = Hasher::HashCode (p->Key1(), NbBuckets()); + const Standard_Integer iK = Hasher::HashCode (p->Key1(), NbBuckets()); IndexedDataMapNode * q = (IndexedDataMapNode *) myData1[iK]; if (q == p) myData1[iK] = (IndexedDataMapNode *) p->Next(); @@ -363,71 +343,26 @@ private: return; } - const Standard_Integer aK1 = ::HashCode (theIndex1, NbBuckets()); - const Standard_Integer aK2 = ::HashCode (theIndex2, NbBuckets()); - - IndexedDataMapNode* aP1 = (IndexedDataMapNode*) myData2[aK1]; - IndexedDataMapNode* aP2 = (IndexedDataMapNode*) myData2[aK2]; - - if (aP1->Key2() == theIndex1) - { - myData2[aK1] = (IndexedDataMapNode *) aP1->Next2(); - } - else - { - IndexedDataMapNode* aQ = aP1; - for (aP1 = aQ->Next2(); aP1->Key2() != theIndex1; aQ = aP1, aP1 = aQ->Next2()) { } - - aQ->Next2() = aP1->Next2(); - } - - if (aP2->Key2() == theIndex2) - { - myData2[aK2] = (IndexedDataMapNode *) aP2->Next2(); - } - else - { - IndexedDataMapNode* aQ = aP2; - for (aP2 = aQ->Next2(); aP2->Key2() != theIndex2; aQ = aP2, aP2 = aQ->Next2()) { } - - aQ->Next2() = aP2->Next2(); - } - - std::swap (aP1->Key2(), - aP2->Key2()); - - aP1->Next2() = (IndexedDataMapNode*) myData2[aK2]; - myData2[aK2] = aP1; - - aP2->Next2() = (IndexedDataMapNode*) myData2[aK1]; - myData2[aK1] = aP2; + IndexedDataMapNode* aP1 = (IndexedDataMapNode* )myData2[theIndex1 - 1]; + IndexedDataMapNode* aP2 = (IndexedDataMapNode* )myData2[theIndex2 - 1]; + std::swap (aP1->Index(), aP2->Index()); + myData2[theIndex2 - 1] = aP1; + myData2[theIndex1 - 1] = aP2; } //! RemoveLast void RemoveLast (void) { - Standard_OutOfRange_Raise_if (Extent() == 0, "NCollection_IndexedDataMap::RemoveLast"); + const Standard_Integer aLastIndex = Extent(); + Standard_OutOfRange_Raise_if (aLastIndex == 0, "NCollection_IndexedDataMap::RemoveLast"); - IndexedDataMapNode * p, * q; // Find the node for the last index and remove it - Standard_Integer iK2 = ::HashCode (Extent(), NbBuckets()); - p = (IndexedDataMapNode *) myData2[iK2]; - q = NULL; - while (p) - { - if (p->Key2() == Extent()) - break; - q = p; - p = (IndexedDataMapNode*) p->Next2(); - } - if (q == NULL) - myData2[iK2] = (IndexedDataMapNode *) p->Next2(); - else - q->Next2() = p->Next2(); + IndexedDataMapNode* p = (IndexedDataMapNode* )myData2[aLastIndex - 1]; + myData2[aLastIndex - 1] = NULL; // remove the key - Standard_Integer iK1 = Hasher::HashCode (p->Key1(), NbBuckets()); - q = (IndexedDataMapNode *) myData1[iK1]; + const Standard_Integer iK1 = Hasher::HashCode (p->Key1(), NbBuckets()); + IndexedDataMapNode* q = (IndexedDataMapNode *) myData1[iK1]; if (q == p) myData1[iK1] = (IndexedDataMapNode *) p->Next(); else @@ -443,12 +378,14 @@ private: //! Remove the key of the given index. //! Caution! The index of the last key can be changed. - void RemoveFromIndex(const Standard_Integer theKey2) + void RemoveFromIndex(const Standard_Integer theIndex) { - Standard_OutOfRange_Raise_if(theKey2 < 1 || theKey2 > Extent(), "NCollection_IndexedDataMap::Remove"); - Standard_Integer aLastInd = Extent(); - if (theKey2 != aLastInd) - Swap(theKey2, aLastInd); + const Standard_Integer aLastInd = Extent(); + Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > aLastInd, "NCollection_IndexedDataMap::Remove"); + if (theIndex != aLastInd) + { + Swap (theIndex, aLastInd); + } RemoveLast(); } @@ -463,62 +400,46 @@ private: } //! FindKey - const TheKeyType& FindKey (const Standard_Integer theKey2) const + const TheKeyType& FindKey (const Standard_Integer theIndex) const { - Standard_OutOfRange_Raise_if (theKey2 < 1 || theKey2 > Extent(), "NCollection_IndexedDataMap::FindKey"); - - IndexedDataMapNode* aNode = nodeFromIndex (theKey2); - if (aNode == NULL) - { - throw Standard_NoSuchObject("NCollection_IndexedDataMap::FindKey"); - } + Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > Extent(), "NCollection_IndexedDataMap::FindKey"); + IndexedDataMapNode* aNode = (IndexedDataMapNode* )myData2[theIndex - 1]; return aNode->Key1(); } //! FindFromIndex - const TheItemType& FindFromIndex (const Standard_Integer theKey2) const + const TheItemType& FindFromIndex (const Standard_Integer theIndex) const { - Standard_OutOfRange_Raise_if (theKey2 < 1 || theKey2 > Extent(), "NCollection_IndexedDataMap::FindFromIndex"); - - IndexedDataMapNode* aNode = nodeFromIndex (theKey2); - if (aNode == NULL) - { - throw Standard_NoSuchObject("NCollection_IndexedDataMap::FindFromIndex"); - } + Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > Extent(), "NCollection_IndexedDataMap::FindFromIndex"); + IndexedDataMapNode* aNode = (IndexedDataMapNode* )myData2[theIndex - 1]; return aNode->Value(); } //! operator () - const TheItemType& operator() (const Standard_Integer theKey2) const - { return FindFromIndex (theKey2); } + const TheItemType& operator() (const Standard_Integer theIndex) const { return FindFromIndex (theIndex); } //! ChangeFromIndex - TheItemType& ChangeFromIndex (const Standard_Integer theKey2) + TheItemType& ChangeFromIndex (const Standard_Integer theIndex) { - Standard_OutOfRange_Raise_if (theKey2 < 1 || theKey2 > Extent(), "NCollection_IndexedDataMap::ChangeFromIndex"); - - IndexedDataMapNode* aNode = nodeFromIndex (theKey2); - if (aNode == NULL) - { - throw Standard_NoSuchObject("NCollection_IndexedDataMap::ChangeFromIndex"); - } + Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > Extent(), "NCollection_IndexedDataMap::ChangeFromIndex"); + IndexedDataMapNode* aNode = (IndexedDataMapNode* )myData2[theIndex - 1]; return aNode->ChangeValue(); } //! operator () - TheItemType& operator() (const Standard_Integer theKey2) - { return ChangeFromIndex (theKey2); } + TheItemType& operator() (const Standard_Integer theIndex) { return ChangeFromIndex (theIndex); } //! FindIndex Standard_Integer FindIndex(const TheKeyType& theKey1) const { if (IsEmpty()) return 0; - IndexedDataMapNode * pNode1 = - (IndexedDataMapNode *) myData1[Hasher::HashCode(theKey1,NbBuckets())]; + IndexedDataMapNode* pNode1 = (IndexedDataMapNode* )myData1[Hasher::HashCode(theKey1,NbBuckets())]; while (pNode1) { - if (Hasher::IsEqual (pNode1->Key1(), theKey1)) - return pNode1->Key2(); + if (Hasher::IsEqual (pNode1->Key1(), theKey1)) + { + return pNode1->Index(); + } pNode1 = (IndexedDataMapNode*) pNode1->Next(); } return 0; @@ -529,12 +450,13 @@ private: { Standard_NoSuchObject_Raise_if (IsEmpty(), "NCollection_IndexedDataMap::FindFromKey"); - IndexedDataMapNode * pNode1 = - (IndexedDataMapNode *) myData1[Hasher::HashCode(theKey1,NbBuckets())]; + IndexedDataMapNode* pNode1 = (IndexedDataMapNode* )myData1[Hasher::HashCode(theKey1,NbBuckets())]; while (pNode1) { - if (Hasher::IsEqual (pNode1->Key1(), theKey1)) + if (Hasher::IsEqual (pNode1->Key1(), theKey1)) + { return pNode1->Value(); + } pNode1 = (IndexedDataMapNode*) pNode1->Next(); } throw Standard_NoSuchObject("NCollection_IndexedDataMap::FindFromKey"); @@ -545,12 +467,13 @@ private: { Standard_NoSuchObject_Raise_if (IsEmpty(), "NCollection_IndexedDataMap::ChangeFromKey"); - IndexedDataMapNode * pNode1 = - (IndexedDataMapNode *) myData1[Hasher::HashCode(theKey1,NbBuckets())]; + IndexedDataMapNode* pNode1 = (IndexedDataMapNode* )myData1[Hasher::HashCode(theKey1,NbBuckets())]; while (pNode1) { - if (Hasher::IsEqual (pNode1->Key1(), theKey1)) + if (Hasher::IsEqual (pNode1->Key1(), theKey1)) + { return pNode1->ChangeValue(); + } pNode1 = (IndexedDataMapNode*) pNode1->Next(); } throw Standard_NoSuchObject("NCollection_IndexedDataMap::ChangeFromKey"); @@ -571,12 +494,13 @@ private: { if (!IsEmpty()) { - IndexedDataMapNode * pNode1 = - (IndexedDataMapNode *) myData1[Hasher::HashCode(theKey1,NbBuckets())]; + IndexedDataMapNode* pNode1 = (IndexedDataMapNode* )myData1[Hasher::HashCode(theKey1,NbBuckets())]; while (pNode1) { - if (Hasher::IsEqual (pNode1->Key1(), theKey1)) + if (Hasher::IsEqual (pNode1->Key1(), theKey1)) + { return &pNode1->ChangeValue(); + } pNode1 = (IndexedDataMapNode*) pNode1->Next(); } } @@ -628,25 +552,6 @@ private: private: // ----------- PRIVATE METHODS ----------- - //! Find map node associated with specified index. - //! Return NULL if not found (exception-free internal implementation). - IndexedDataMapNode* nodeFromIndex (const Standard_Integer theKey2) const - { - if (Extent() == 0) - { - return NULL; - } - for (IndexedDataMapNode* aNode = (IndexedDataMapNode* )myData2[::HashCode (theKey2, NbBuckets())]; - aNode != NULL; aNode = (IndexedDataMapNode* )aNode->Next2()) - { - if (aNode->Key2() == theKey2) - { - return aNode; - } - } - return NULL; - } - }; #endif diff --git a/src/NCollection/NCollection_IndexedMap.hxx b/src/NCollection/NCollection_IndexedMap.hxx index f9a150c06e..fe3c4a7f77 100644 --- a/src/NCollection/NCollection_IndexedMap.hxx +++ b/src/NCollection/NCollection_IndexedMap.hxx @@ -44,30 +44,24 @@ public: //! STL-compliant typedef for key type typedef TheKeyType key_type; - private: - // **************** Adaptation of the TListNode to the INDEXEDmap - class IndexedMapNode : public NCollection_TListNode +private: + //! Adaptation of the TListNode to the INDEXEDmap + class IndexedMapNode : public NCollection_TListNode { public: //! Constructor with 'Next' IndexedMapNode (const TheKeyType& theKey1, - const Standard_Integer theKey2, - NCollection_ListNode* theNext1, - NCollection_ListNode* theNext2) : - NCollection_TListNode (theKey1, theNext1), - myKey2(theKey2), - myNext2((IndexedMapNode*)theNext2) - { + const Standard_Integer theIndex, + NCollection_ListNode* theNext1) + : NCollection_TListNode (theKey1, theNext1), + myIndex (theIndex) + { } //! Key1 - TheKeyType& Key1 (void) - { return this->ChangeValue(); } - //! Key2 - Standard_Integer& Key2 (void) - { return myKey2; } - //! Next2 - IndexedMapNode*& Next2 (void) - { return myNext2; } + TheKeyType& Key1() { return this->ChangeValue(); } + + //! Index + Standard_Integer& Index() { return myIndex; } //! Static deleter to be passed to BaseList static void delNode (NCollection_ListNode * theNode, @@ -78,8 +72,7 @@ public: } private: - Standard_Integer myKey2; - IndexedMapNode * myNext2; + Standard_Integer myIndex; }; public: @@ -157,17 +150,14 @@ public: Clear(); ReSize (theOther.Extent()-1); - Standard_Integer i, iLength=theOther.Extent(); - for (i=1; i<=iLength; i++) + const Standard_Integer iLength = theOther.Extent(); + for (Standard_Integer anIndexIter = 1; anIndexIter <= iLength; ++anIndexIter) { - TheKeyType aKey1 = theOther(i); - Standard_Integer iK1 = Hasher::HashCode (aKey1, NbBuckets()); - Standard_Integer iK2 = ::HashCode (i, NbBuckets()); - IndexedMapNode * pNode = new (this->myAllocator) IndexedMapNode (aKey1, i, - myData1[iK1], - myData2[iK2]); - myData1[iK1] = pNode; - myData2[iK2] = pNode; + const TheKeyType& aKey1 = theOther.FindKey (anIndexIter); + const Standard_Integer iK1 = Hasher::HashCode (aKey1, NbBuckets()); + IndexedMapNode* pNode = new (this->myAllocator) IndexedMapNode (aKey1, anIndexIter, myData1[iK1]); + myData1[iK1] = pNode; + myData2[anIndexIter - 1] = pNode; Increment(); } return *this; @@ -180,64 +170,60 @@ public: } //! ReSize - void ReSize (const Standard_Integer N) + void ReSize (const Standard_Integer theExtent) { NCollection_ListNode** ppNewData1 = NULL; NCollection_ListNode** ppNewData2 = NULL; Standard_Integer newBuck; - if (BeginResize (N, newBuck, ppNewData1, ppNewData2)) + if (BeginResize (theExtent, newBuck, ppNewData1, ppNewData2)) { if (myData1) { - IndexedMapNode *p, *q; - Standard_Integer i, iK1, iK2; - for (i = 0; i <= NbBuckets(); i++) + memcpy (ppNewData2, myData2, sizeof(IndexedMapNode*) * Extent()); + for (Standard_Integer aBucketIter = 0; aBucketIter <= NbBuckets(); ++aBucketIter) { - if (myData1[i]) + if (myData1[aBucketIter]) { - p = (IndexedMapNode *) myData1[i]; + IndexedMapNode* p = (IndexedMapNode* )myData1[aBucketIter]; while (p) { - iK1 =Hasher::HashCode(p->Key1(), newBuck); - q = (IndexedMapNode*) p->Next(); - p->Next() = ppNewData1[iK1]; + const Standard_Integer iK1 = Hasher::HashCode (p->Key1(), newBuck); + IndexedMapNode* q = (IndexedMapNode* )p->Next(); + p->Next() = ppNewData1[iK1]; ppNewData1[iK1] = p; - if (p->Key2() > 0) - { - iK2 = ::HashCode (p->Key2(), newBuck); - p->Next2() = (IndexedMapNode*)ppNewData2[iK2]; - ppNewData2[iK2] = p; - } p = q; } } } } - EndResize (N, newBuck, ppNewData1, ppNewData2); + EndResize (theExtent, newBuck, ppNewData1, ppNewData2); } } //! Add Standard_Integer Add (const TheKeyType& theKey1) { - if (Resizable()) - ReSize(Extent()); + if (Resizable()) + { + ReSize (Extent()); + } + Standard_Integer iK1 = Hasher::HashCode (theKey1, NbBuckets()); - IndexedMapNode * pNode; - pNode = (IndexedMapNode *) myData1[iK1]; + IndexedMapNode* pNode = (IndexedMapNode* )myData1[iK1]; while (pNode) { if (Hasher::IsEqual (pNode->Key1(), theKey1)) - return pNode->Key2(); + { + return pNode->Index(); + } pNode = (IndexedMapNode *) pNode->Next(); } - Increment(); - Standard_Integer iK2 = ::HashCode(Extent(),NbBuckets()); - pNode = new (this->myAllocator) IndexedMapNode (theKey1, Extent(), - myData1[iK1], myData2[iK2]); - myData1[iK1] = pNode; - myData2[iK2] = pNode; - return Extent(); + + const Standard_Integer aNewIndex = Increment(); + pNode = new (this->myAllocator) IndexedMapNode (theKey1, aNewIndex, myData1[iK1]); + myData1[iK1] = pNode; + myData2[aNewIndex - 1] = pNode; + return aNewIndex; } //! Contains @@ -265,15 +251,14 @@ public: "NCollection_IndexedMap::Substitute : " "Index is out of range"); - IndexedMapNode * p; // check if theKey1 is not already in the map Standard_Integer iK1 = Hasher::HashCode (theKey1, NbBuckets()); - p = (IndexedMapNode *) myData1[iK1]; + IndexedMapNode* p = (IndexedMapNode *) myData1[iK1]; while (p) { if (Hasher::IsEqual (p->Key1(), theKey1)) { - if (p->Key2() != theIndex) + if (p->Index() != theIndex) { throw Standard_DomainError ("NCollection_IndexedMap::Substitute : " "Attempt to substitute existing key"); @@ -285,14 +270,7 @@ public: } // Find the node for the index I - Standard_Integer iK2 = ::HashCode (theIndex, NbBuckets()); - p = (IndexedMapNode *) myData2[iK2]; - while (p) - { - if (p->Key2() == theIndex) - break; - p = (IndexedMapNode*) p->Next2(); - } + p = (IndexedMapNode* )myData2[theIndex - 1]; // remove the old key Standard_Integer iK = Hasher::HashCode (p->Key1(), NbBuckets()); @@ -324,71 +302,26 @@ public: return; } - const Standard_Integer aK1 = ::HashCode (theIndex1, NbBuckets()); - const Standard_Integer aK2 = ::HashCode (theIndex2, NbBuckets()); - - IndexedMapNode* aP1 = (IndexedMapNode*) myData2[aK1]; - IndexedMapNode* aP2 = (IndexedMapNode*) myData2[aK2]; - - if (aP1->Key2() == theIndex1) - { - myData2[aK1] = (IndexedMapNode *) aP1->Next2(); - } - else - { - IndexedMapNode* aQ = aP1; - for (aP1 = aQ->Next2(); aP1->Key2() != theIndex1; aQ = aP1, aP1 = aQ->Next2()) { } - - aQ->Next2() = aP1->Next2(); - } - - if (aP2->Key2() == theIndex2) - { - myData2[aK2] = (IndexedMapNode *) aP2->Next2(); - } - else - { - IndexedMapNode* aQ = aP2; - for (aP2 = aQ->Next2(); aP2->Key2() != theIndex2; aQ = aP2, aP2 = aQ->Next2()) { } - - aQ->Next2() = aP2->Next2(); - } - - std::swap (aP1->Key2(), - aP2->Key2()); - - aP1->Next2() = (IndexedMapNode*) myData2[aK2]; - myData2[aK2] = aP1; - - aP2->Next2() = (IndexedMapNode*) myData2[aK1]; - myData2[aK1] = aP2; + IndexedMapNode* aP1 = (IndexedMapNode* )myData2[theIndex1 - 1]; + IndexedMapNode* aP2 = (IndexedMapNode* )myData2[theIndex2 - 1]; + std::swap (aP1->Index(), aP2->Index()); + myData2[theIndex2 - 1] = aP1; + myData2[theIndex1 - 1] = aP2; } //! RemoveLast void RemoveLast (void) { - Standard_OutOfRange_Raise_if (Extent() == 0, "NCollection_IndexedMap::RemoveLast"); + const Standard_Integer aLastIndex = Extent(); + Standard_OutOfRange_Raise_if (aLastIndex == 0, "NCollection_IndexedMap::RemoveLast"); - IndexedMapNode * p, * q; // Find the node for the last index and remove it - Standard_Integer iK2 = ::HashCode (Extent(), NbBuckets()); - p = (IndexedMapNode *) myData2[iK2]; - q = NULL; - while (p) - { - if (p->Key2() == Extent()) - break; - q = p; - p = (IndexedMapNode*) p->Next2(); - } - if (q == NULL) - myData2[iK2] = (IndexedMapNode *) p->Next2(); - else - q->Next2() = p->Next2(); - + IndexedMapNode* p = (IndexedMapNode* )myData2[aLastIndex - 1]; + myData2[aLastIndex - 1] = NULL; + // remove the key Standard_Integer iK1 = Hasher::HashCode (p->Key1(), NbBuckets()); - q = (IndexedMapNode *) myData1[iK1]; + IndexedMapNode* q = (IndexedMapNode *) myData1[iK1]; if (q == p) myData1[iK1] = (IndexedMapNode *) p->Next(); else @@ -404,12 +337,14 @@ public: //! Remove the key of the given index. //! Caution! The index of the last key can be changed. - void RemoveFromIndex(const Standard_Integer theKey2) + void RemoveFromIndex(const Standard_Integer theIndex) { - Standard_OutOfRange_Raise_if(theKey2 < 1 || theKey2 > Extent(), "NCollection_IndexedMap::Remove"); - Standard_Integer aLastInd = Extent(); - if (theKey2 != aLastInd) - Swap(theKey2, aLastInd); + Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > Extent(), "NCollection_IndexedMap::RemoveFromIndex"); + const Standard_Integer aLastInd = Extent(); + if (theIndex != aLastInd) + { + Swap(theIndex, aLastInd); + } RemoveLast(); } @@ -428,35 +363,28 @@ public: } //! FindKey - const TheKeyType& FindKey (const Standard_Integer theKey2) const + const TheKeyType& FindKey (const Standard_Integer theIndex) const { - Standard_OutOfRange_Raise_if (theKey2 < 1 || theKey2 > Extent(), "NCollection_IndexedMap::FindKey"); - - IndexedMapNode * pNode2 = - (IndexedMapNode *) myData2[::HashCode(theKey2,NbBuckets())]; - while (pNode2) - { - if (pNode2->Key2() == theKey2) - return pNode2->Key1(); - pNode2 = (IndexedMapNode*) pNode2->Next2(); - } - throw Standard_NoSuchObject("NCollection_IndexedMap::FindKey"); + Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > Extent(), "NCollection_IndexedMap::FindKey"); + IndexedMapNode* pNode2 = (IndexedMapNode* )myData2[theIndex - 1]; + return pNode2->Key1(); } //! operator () - const TheKeyType& operator() (const Standard_Integer theKey2) const - { return FindKey (theKey2); } + const TheKeyType& operator() (const Standard_Integer theIndex) const + { return FindKey (theIndex); } //! FindIndex Standard_Integer FindIndex(const TheKeyType& theKey1) const { if (IsEmpty()) return 0; - IndexedMapNode * pNode1 = - (IndexedMapNode *) myData1[Hasher::HashCode(theKey1,NbBuckets())]; + IndexedMapNode* pNode1 = (IndexedMapNode* )myData1[Hasher::HashCode(theKey1,NbBuckets())]; while (pNode1) { - if (Hasher::IsEqual (pNode1->Key1(), theKey1)) - return pNode1->Key2(); + if (Hasher::IsEqual (pNode1->Key1(), theKey1)) + { + return pNode1->Index(); + } pNode1 = (IndexedMapNode*) pNode1->Next(); } return 0; diff --git a/src/TCollection/TCollection.cxx b/src/TCollection/TCollection.cxx index cede6e4592..667b058423 100644 --- a/src/TCollection/TCollection.cxx +++ b/src/TCollection/TCollection.cxx @@ -14,9 +14,10 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. - #include +#include + // The array of prime numbers used as consequtive steps for // size of array of buckets in the map. // The prime numbers are used for array size with the hope that this will @@ -27,27 +28,47 @@ // memory overhead in that case is only ~15% as compared with total size of // all auxiliary data structures (each map node takes ~24 bytes), // and this proves to pay off in performance (see OCC13189). -#define NB_PRIMES 12 -static const Standard_Integer Primes[NB_PRIMES+1] = { - 101, - 1009, - 2003, - 5003, - 10007, - 20011, - 37003, - 57037, - 65003, - 100019, - 209953, // The following are Pierpont primes taken from Wikipedia [List of prime numbers] - 472393, - 995329 -}; +#define THE_NB_PRIMES 24 +static const Standard_Integer THE_TCollection_Primes[THE_NB_PRIMES] = +{ + 101, + 1009, + 2003, + 5003, + 10007, + 20011, + 37003, + 57037, + 65003, + 100019, + 209953, // The following are Pierpont primes [List of prime numbers] + 472393, + 995329, + 2359297, + 4478977, + 9437185, + 17915905, + 35831809, + 71663617, + 150994945, + 301989889, + 573308929, + 1019215873, + 2038431745 +}; +// ======================================================================= +// function : NextPrimeForMap +// purpose : +// ======================================================================= Standard_Integer TCollection::NextPrimeForMap(const Standard_Integer N) { - Standard_Integer i; - for (i = 0; i < NB_PRIMES; i++) - if (Primes[i] > N) break; - return Primes[i]; + for (Standard_Integer aPrimeIter = 0; aPrimeIter < THE_NB_PRIMES; ++aPrimeIter) + { + if (THE_TCollection_Primes[aPrimeIter] > N) + { + return THE_TCollection_Primes[aPrimeIter]; + } + } + throw Standard_OutOfRange ("TCollection::NextPrimeForMap() - requested too big size"); }