#include <TColStd_PackedMapOfInteger.hxx>
-#include <TCollection_MapNode.hxx>
+#include <NCollection_Array1.hxx>
+#include <TCollection.hxx>
#include <Standard_Type.hxx>
-// 5 lower bits
-#define MASK_LOW 0x001F
-// 27 upper bits
-#define MASK_HIGH (~MASK_LOW)
-
-namespace
-{
- //! Returns the key with applied mask to it
- //! @param theKey the given key
- //! @return the key with the applied mask to it
- unsigned int maskedKey (const unsigned int theKey)
- {
- return theKey & MASK_HIGH;
- }
-
- //! Computes a hash code for the given key (using only masked bits) in the range [1, theUpperBound]
- //! @param theKey the given key
- //! @param theUpperBound the upper bound of the range a computing hash code must be within
- //! @return a computed hash code, in the range [1, theUpperBound]
- Standard_Integer hashCodeForKey (const unsigned int theKey, const Standard_Integer theUpperBound)
- {
- return HashCode (theKey >> 5, theUpperBound);
- }
-
- //! Computes a hash code for the given key (using only masked bits) in the range [1, theUpperBound]
- //! @param theKey the given key
- //! @param theUpperBound the upper bound of the range a computing hash code must be within
- //! @return a computed hash code, in the range [1, theUpperBound]
- Standard_Integer hashCodeForKey (const Standard_Integer theKey, const Standard_Integer theUpperBound)
- {
- return hashCodeForKey (static_cast<unsigned int> (theKey), theUpperBound);
- }
-} // namespace
-
-//! Class implementing a block of 32 consecutive integer values as a node of a Map collection.
-class TColStd_PackedMapOfInteger::TColStd_intMapNode : public TCollection_MapNode
-{
-public:
- explicit inline TColStd_intMapNode (TCollection_MapNode * ptr = 0L)
- : TCollection_MapNode (ptr),
- myMask (0),
- myData (0) {}
-
- inline TColStd_intMapNode (const Standard_Integer theValue,
- TCollection_MapNode *& ptr)
- : TCollection_MapNode (ptr),
- myMask ((unsigned int) (theValue & MASK_HIGH)),
- myData (1 << (theValue & MASK_LOW)) {}
-
- inline TColStd_intMapNode (unsigned int theMask,
- unsigned int theData,
- TCollection_MapNode * ptr)
- : TCollection_MapNode (ptr),
- myMask (theMask),
- myData (theData) {}
-
- inline unsigned int Mask () const
- { return myMask; }
-
- inline unsigned int Data () const
- { return myData; }
-
- inline unsigned int& ChangeMask ()
- { return myMask; }
-
- inline unsigned int& ChangeData ()
- { return myData; }
-
- inline Standard_Integer Key() const
- {
- return static_cast<Standard_Integer> (maskedKey());
- }
-
- inline size_t NbValues () const
- { return size_t(myMask & MASK_LOW) + 1; }
-
- inline Standard_Boolean HasValues () const
- { return (myData != 0); }
-
- Standard_Integer HasValue (const Standard_Integer theValue) const
- { return (myData & (1 << (theValue & MASK_LOW))); }
-
- Standard_Boolean AddValue (const Standard_Integer theValue);
-
- Standard_Boolean DelValue (const Standard_Integer theValue);
-
- /**
- * Find the smallest non-zero bit under the given mask. Outputs the new mask
- * that does not contain the detected bit.
- */
- Standard_Integer FindNext (unsigned int& theMask) const;
-
- //! Computes a hash code for this map in the range [1, theUpperBound]
- //! @param theUpperBound the upper bound of the range a computing hash code must be within
- //! @return a computed hash code, in the range [1, theUpperBound]
- inline Standard_Integer HashCode (const Standard_Integer theUpperBound) const
- {
- return hashCodeForKey (myMask, theUpperBound);
- }
-
- //! Checks this node's key on equality with some other key
- //! @param theOtherKey the given unmasked key
- //! @return true if this node's masked key is equal to the given key with applied mask, or false otherwise
- inline Standard_Boolean IsEqual (const Standard_Integer theOtherKey) const
- {
- return isEqual (::maskedKey (static_cast<unsigned int> (theOtherKey)));
- }
-
- //! Checks this node's key on equality with some other node's key
- //! @param theOtherMapNode the given other map node
- //! @return true if this node's masked key is equal to the given other map node's masked key, or false otherwise
- bool IsEqual (const TColStd_intMapNode& theOtherMapNode) const
- {
- return isEqual (theOtherMapNode.maskedKey());
- }
-
-private:
- //! Returns the key of this map node with the mask applied to it
- unsigned int maskedKey() const
- {
- return ::maskedKey (myMask);
- }
-
- //! Checks this node's key on equality with some other masked key
- //! @param theOtherMaskedKey the given masked key
- //! @return true if this node's masked key is equal to the given masked key, or false otherwise
- bool isEqual (const unsigned int theOtherMaskedKey) const
- {
- return maskedKey() == theOtherMaskedKey;
- }
-
-private:
- unsigned int myMask;
- unsigned int myData;
-};
-
-
-//=======================================================================
-//function : TColStd_intMapNode::AddValue
-//purpose :
-//=======================================================================
-
-Standard_Boolean TColStd_PackedMapOfInteger::TColStd_intMapNode::AddValue (const Standard_Integer theValue)
-{
- Standard_Boolean aResult (Standard_False);
- const Standard_Integer aValInt = (1 << (theValue & MASK_LOW));
- if ((myData & aValInt) == 0) {
- myData ^= aValInt;
- myMask++;
- aResult = Standard_True;
- }
- return aResult;
-}
-
-//=======================================================================
-//function : TColStd_intMapNode::DelValue
-//purpose :
-//=======================================================================
-
-Standard_Boolean TColStd_PackedMapOfInteger::TColStd_intMapNode::DelValue (const Standard_Integer theValue)
-{
- Standard_Boolean aResult (Standard_False);
- const Standard_Integer aValInt = (1 << (theValue & MASK_LOW));
- if ((myData & aValInt) != 0) {
- myData ^= aValInt;
- myMask--;
- aResult = Standard_True;
- }
- return aResult;
-}
-
-//=======================================================================
-//function : TColStd_Population
-//purpose : Compute the population (i.e., the number of non-zero bits) of
-// the 32-bit word theData. The population is stored decremented
-// as it is defined in TColStd_intMapNode.
-//source : H.S.Warren, Hacker''s Delight, Addison-Wesley Inc. 2002, Ch.5.1
-//=======================================================================
-
-inline size_t TColStd_Population (unsigned int& theMask,
- const unsigned int theData)
-{
- unsigned int aRes = theData - ((theData>>1) & 0x55555555);
- aRes = (aRes & 0x33333333) + ((aRes>>2) & 0x33333333);
- aRes = (aRes + (aRes>>4)) & 0x0f0f0f0f;
- aRes = aRes + (aRes>>8);
- aRes = aRes + (aRes>>16);
- theMask = (theMask & MASK_HIGH) | ((aRes-1) & MASK_LOW);
- return (size_t) (aRes & 0x3f);
-}
-
//=======================================================================
//function : TColStd_intMapNode_findNext
//purpose :
if (this != &theOther) {
Clear();
if (!theOther.IsEmpty()) {
- ReSize (theOther.InternalExtent());
- const Standard_Integer nBucketsSrc = theOther.NbBuckets();
- const Standard_Integer nBuckets = NbBuckets();
- const TColStd_intMapNode** aDataSrc =
- (const TColStd_intMapNode**) theOther.myData1;
- TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
- for (Standard_Integer i = 0; i <= nBucketsSrc; i++) {
- const TColStd_intMapNode * p = aDataSrc[i];
- while (p) {
+ ReSize (theOther.myNbPackedMapNodes);
+ const Standard_Integer nBucketsSrc = theOther.myNbBuckets;
+ const Standard_Integer nBuckets = myNbBuckets;
+ for (Standard_Integer i = 0; i <= nBucketsSrc; i++)
+ {
+ for (const TColStd_intMapNode* p = theOther.myData1[i]; p != NULL; )
+ {
const Standard_Integer aHashCode = p->HashCode(nBuckets);
- aData[aHashCode] =
- new TColStd_intMapNode (p->Mask(), p->Data(), aData[aHashCode]);
- Increment();
- p = static_cast <const TColStd_intMapNode*> (p->Next());
+ myData1[aHashCode] = new TColStd_intMapNode (p->Mask(), p->Data(), myData1[aHashCode]);
+ ++myNbPackedMapNodes;
+ p = p->Next();
}
}
// TColStd_MapIteratorOfPackedMapOfInteger anIt (theOther);
//purpose :
//=======================================================================
-void TColStd_PackedMapOfInteger::ReSize (const Standard_Integer nbBuckets)
+void TColStd_PackedMapOfInteger::ReSize (const Standard_Integer theNbBuckets)
{
- Standard_Integer newBuck;
- Standard_Address newData1=NULL, dummy=NULL;
- if (BeginResize (nbBuckets, newBuck, newData1, dummy))
+ Standard_Integer aNewBuck = TCollection::NextPrimeForMap (theNbBuckets);
+ if (aNewBuck <= myNbBuckets)
{
- if (myData1) {
- TColStd_intMapNode** newdata =
- reinterpret_cast <TColStd_intMapNode**> (newData1);
- TColStd_intMapNode** olddata =
- reinterpret_cast <TColStd_intMapNode**> (myData1);
- TColStd_intMapNode * p;
- Standard_Integer i,k;
- for (i = 0; i <= NbBuckets(); i++) {
- if (olddata[i]) {
- p = olddata[i];
- while (p) {
- k = p->HashCode(newBuck);
- TCollection_MapNode * q = p->Next();
- p->Next() = newdata[k];
- newdata[k] = p;
- p = static_cast <TColStd_intMapNode*> (q);
- }
- }
+ if (!IsEmpty())
+ {
+ return;
+ }
+ aNewBuck = myNbBuckets;
+ }
+
+ TColStd_intMapNode** aNewData = (TColStd_intMapNode** )Standard::Allocate ((aNewBuck + 1) * sizeof(TColStd_intMapNode*));
+ memset (aNewData, 0, (aNewBuck + 1) * sizeof(TColStd_intMapNode*));
+ if (myData1 != NULL)
+ {
+ TColStd_intMapNode** anOldData = myData1;
+ for (Standard_Integer i = 0; i <= myNbBuckets; ++i)
+ {
+ for (TColStd_intMapNode* p = anOldData[i]; p != NULL; )
+ {
+ Standard_Integer k = p->HashCode (aNewBuck);
+ TColStd_intMapNode* q = p->Next();
+ p->SetNext (aNewData[k]);
+ aNewData[k] = p;
+ p = q;
}
}
- EndResize (nbBuckets, newBuck, newData1, dummy);
}
+
+ Standard::Free (myData1);
+ myNbBuckets = aNewBuck;
+ myData1 = aNewData;
}
//=======================================================================
void TColStd_PackedMapOfInteger::Clear ()
{
- if (!IsEmpty()) {
- Standard_Integer i;
- TColStd_intMapNode** data =
- reinterpret_cast <TColStd_intMapNode**> (myData1);
- TColStd_intMapNode * p;
- for (i = 0; i <= NbBuckets(); i++) {
- if (data[i]) {
- p = data[i];
- while (p) {
- TCollection_MapNode * q = p->Next();
- delete p;
- p = static_cast <TColStd_intMapNode*> (q);
- }
+ if (!IsEmpty())
+ {
+ for (Standard_Integer aBucketIter = 0; aBucketIter <= myNbBuckets; ++aBucketIter)
+ {
+ if (myData1[aBucketIter])
+ {
+ for (TColStd_intMapNode* aSubNodeIter = myData1[aBucketIter]; aSubNodeIter != NULL; )
+ {
+ TColStd_intMapNode* q = aSubNodeIter->Next();
+ delete aSubNodeIter;
+ aSubNodeIter = q;
+ }
}
}
}
- TCollection_BasicMap::Destroy();
+
+ myNbPackedMapNodes = 0;
+ Standard::Free (myData1);
+ myData1 = NULL;
myExtent = 0;
}
Standard_Boolean TColStd_PackedMapOfInteger::Add (const Standard_Integer aKey)
{
if (Resizable())
- ReSize(InternalExtent());
- Standard_Boolean aResult (Standard_False);
- TColStd_intMapNode ** data =
- reinterpret_cast <TColStd_intMapNode**> (myData1);
- const Standard_Integer aHashCode = hashCodeForKey (aKey, NbBuckets());
- TCollection_MapNodePtr aBucketHead = data[aHashCode];
- TColStd_intMapNode * p = static_cast<TColStd_intMapNode*> (aBucketHead);
- while (p) {
- if (p->IsEqual(aKey)) {
- aResult = p->AddValue (aKey);
-// break;
- goto finish; // goto saves us 4 CPU clocks or 4% performance
+ {
+ ReSize (myNbPackedMapNodes);
+ }
+
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
+ const Standard_Integer aHashCode = HashCode (aKeyInt, myNbBuckets);
+ TColStd_intMapNode* aBucketHead = myData1[aHashCode];
+ for (TColStd_intMapNode* p = aBucketHead; p != NULL; p = p->Next())
+ {
+ if (p->IsEqual(aKeyInt))
+ {
+ if (p->AddValue (aKey))
+ {
+ ++myExtent;
+ return Standard_True;
+ }
+ return Standard_False;
}
- p = static_cast <TColStd_intMapNode*> (p->Next());
}
-// if (!p) { // not needed, as long as we exit the loop by goto
- data[aHashCode] = new TColStd_intMapNode(aKey, aBucketHead);
- Increment();
- aResult = Standard_True;
-// }
- finish:
- if (aResult)
- myExtent++;
- return aResult;
+
+ myData1[aHashCode] = new TColStd_intMapNode (aKey, aBucketHead);
+ ++myNbPackedMapNodes;
+ ++myExtent;
+ return Standard_True;
}
//=======================================================================
Standard_Boolean TColStd_PackedMapOfInteger::Contains
(const Standard_Integer aKey) const
{
- Standard_Boolean aResult (Standard_False);
- if (!IsEmpty()) {
- TColStd_intMapNode** data = (TColStd_intMapNode**) myData1;
- TColStd_intMapNode * p = data[hashCodeForKey (aKey, NbBuckets())];
- while (p) {
- if (p->IsEqual(aKey)) {
- aResult = (p->HasValue (aKey) != 0);
- break;
- }
- p = static_cast <TColStd_intMapNode*> (p->Next());
+ if (IsEmpty())
+ {
+ return Standard_False;
+ }
+
+ Standard_Boolean aResult = Standard_False;
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
+ for (TColStd_intMapNode* p = myData1[HashCode (aKeyInt, myNbBuckets)]; p != NULL; )
+ {
+ if (p->IsEqual(aKeyInt))
+ {
+ aResult = (p->HasValue (aKey) != 0);
+ break;
}
+ p = p->Next();
}
return aResult;
}
Standard_Boolean TColStd_PackedMapOfInteger::Remove(const Standard_Integer aKey)
{
+ if (IsEmpty())
+ {
+ return Standard_False;
+ }
+
Standard_Boolean aResult (Standard_False);
- if (!IsEmpty()) {
- TColStd_intMapNode** data =
- reinterpret_cast <TColStd_intMapNode**> (myData1);
- TColStd_intMapNode*& aBucketHead = data[hashCodeForKey(aKey, NbBuckets())];
- TColStd_intMapNode* p = aBucketHead;
- TColStd_intMapNode* q = 0L;
- while (p) {
- if (p->IsEqual(aKey)) {
- aResult = p->DelValue (aKey);
- if (aResult) {
- myExtent--;
- if (p->HasValues() == Standard_False) {
- Decrement();
- if (q) q->Next() = p->Next();
- else aBucketHead = static_cast<TColStd_intMapNode*>(p->Next());
- delete p;
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
+ TColStd_intMapNode*& aBucketHead = myData1[HashCode(aKeyInt, myNbBuckets)];
+ TColStd_intMapNode* p = aBucketHead;
+ TColStd_intMapNode* q = 0L;
+ while (p)
+ {
+ if (p->IsEqual(aKeyInt))
+ {
+ aResult = p->DelValue (aKey);
+ if (aResult)
+ {
+ --myExtent;
+ if (!p->HasValues())
+ {
+ --myNbPackedMapNodes;
+ if (q != NULL)
+ {
+ q->SetNext (p->Next());
+ }
+ else
+ {
+ aBucketHead = p->Next();
}
+ delete p;
}
- break;
}
- q = p;
- p = static_cast <TColStd_intMapNode*> (p->Next());
+ break;
}
+ q = p;
+ p = p->Next();
}
return aResult;
}
Standard_Integer TColStd_PackedMapOfInteger::GetMinimalMapped () const
{
+ if (IsEmpty())
+ {
+ return IntegerLast();
+ }
+
Standard_Integer aResult (IntegerLast());
- if (!IsEmpty()) {
- const TCollection_MapNode** aData = (const TCollection_MapNode**) myData1;
- const TColStd_intMapNode * pFoundNode = 0L;
- for (Standard_Integer i = 0; i <= NbBuckets(); i++) {
- for (const TCollection_MapNode * p = aData[i]; p != 0L; p = p->Next()) {
- const Standard_Integer aKey = static_cast <const TColStd_intMapNode *>(p)->Key();
- if (aResult > aKey) {
- aResult = aKey;
- pFoundNode = static_cast<const TColStd_intMapNode *>(p);
- }
+ const TColStd_intMapNode* pFoundNode = 0L;
+ for (Standard_Integer i = 0; i <= myNbBuckets; i++)
+ {
+ for (const TColStd_intMapNode* p = myData1[i]; p != 0L; p = p->Next())
+ {
+ const Standard_Integer aKey = p->Key();
+ if (aResult > aKey)
+ {
+ aResult = aKey;
+ pFoundNode = p;
}
}
- if (pFoundNode) {
- unsigned int aFullMask (0xffffffff);
- aResult = TColStd_intMapNode_findNext ((Standard_Address )pFoundNode, aFullMask);
- }
+ }
+ if (pFoundNode)
+ {
+ unsigned int aFullMask (0xffffffff);
+ aResult = TColStd_intMapNode_findNext ((const Standard_Address )pFoundNode, aFullMask);
}
return aResult;
}
Standard_Integer TColStd_PackedMapOfInteger::GetMaximalMapped () const
{
+ if (IsEmpty())
+ {
+ return IntegerFirst();
+ }
+
Standard_Integer aResult (IntegerFirst());
- if (!IsEmpty()) {
- const TCollection_MapNode** aData = (const TCollection_MapNode**) myData1;
- const TColStd_intMapNode * pFoundNode = 0L;
- for (Standard_Integer i = 0; i <= NbBuckets(); i++) {
- for (const TCollection_MapNode * p = aData[i]; p != 0L; p = p->Next()) {
- const Standard_Integer aKey = static_cast <const TColStd_intMapNode *>(p)->Key();
- if (aResult < aKey) {
- aResult = aKey;
- pFoundNode = static_cast<const TColStd_intMapNode *>(p);
- }
+ const TColStd_intMapNode* pFoundNode = 0L;
+ for (Standard_Integer i = 0; i <= myNbBuckets; i++)
+ {
+ for (const TColStd_intMapNode* p = myData1[i]; p != 0L; p = p->Next())
+ {
+ const Standard_Integer aKey = p->Key();
+ if (aResult < aKey)
+ {
+ aResult = aKey;
+ pFoundNode = p;
}
}
- if (pFoundNode) {
- unsigned int aFullMask (0xffffffff);
- aResult = TColStd_intMapNode_findPrev ((Standard_Address )pFoundNode, aFullMask);
- }
+ }
+ if (pFoundNode)
+ {
+ unsigned int aFullMask (0xffffffff);
+ aResult = TColStd_intMapNode_findPrev ((const Standard_Address )pFoundNode, aFullMask);
}
return aResult;
}
else if (myData1 == theMap2.myData1)
Unite (theMap1);
else {
- Standard_Integer i;
- const TColStd_intMapNode** aData1 =
- (const TColStd_intMapNode**) theMap1.myData1;
- const TColStd_intMapNode** aData2 =
- (const TColStd_intMapNode**) theMap2.myData1;
- const Standard_Integer nBuckets1 = theMap1.NbBuckets();
- const Standard_Integer nBuckets2 = theMap2.NbBuckets();
+ const Standard_Integer nBuckets1 = theMap1.myNbBuckets;
+ const Standard_Integer nBuckets2 = theMap2.myNbBuckets;
Clear();
- TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
// Iteration of the 1st map.
- for (i = 0; i <= nBuckets1; i++) {
- const TColStd_intMapNode * p1 = aData1[i];
+ for (Standard_Integer i = 0; i <= nBuckets1; i++) {
+ const TColStd_intMapNode* p1 = theMap1.myData1[i];
while (p1 != 0L) {
+ // Find aKey - the base address of currently iterated block
+ const Standard_Integer aKey = p1->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
unsigned int aNewMask = p1->Mask();
unsigned int aNewData = p1->Data();
size_t nValues (p1->NbValues());
// Find the corresponding block in the 2nd map
- const TColStd_intMapNode * p2 =
- aData2 [p1->HashCode(nBuckets2)];
+ const TColStd_intMapNode* p2 = theMap2.myData1[HashCode (aKeyInt, nBuckets2)];
while (p2) {
- if (p2->IsEqual(*p1)) {
+ if (p2->IsEqual(aKeyInt)) {
aNewData |= p2->Data();
nValues = TColStd_Population (aNewMask, aNewData);
break;
}
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+ p2 = p2->Next();
}
// Store the block - result of operation
if (Resizable()) {
- ReSize(InternalExtent());
- aData = (TColStd_intMapNode**) myData1;
+ ReSize (myNbPackedMapNodes);
}
- const Standard_Integer aHashCode = p1->HashCode (NbBuckets());
- aData[aHashCode] = new TColStd_intMapNode (aNewMask, aNewData,
- aData[aHashCode]);
- Increment();
+ const Standard_Integer aHashCode = HashCode (aKeyInt, myNbBuckets);
+ myData1[aHashCode] = new TColStd_intMapNode (aNewMask, aNewData,
+ myData1[aHashCode]);
+ ++myNbPackedMapNodes;
myExtent += nValues;
- p1 = static_cast <const TColStd_intMapNode*> (p1->Next());
+ p1 = p1->Next();
}
}
// Iteration of the 2nd map.
- for (i = 0; i <= nBuckets2; i++) {
- const TColStd_intMapNode * p2 = aData2[i];
- while (p2 != 0L) {
+ for (Standard_Integer i = 0; i <= nBuckets2; i++)
+ {
+ const TColStd_intMapNode* p2 = theMap2.myData1[i];
+ while (p2 != 0L)
+ {
+ // Find aKey - the base address of currently iterated block
+ const Standard_Integer aKey = p2->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
// Find the corresponding block in the 1st map
- const TColStd_intMapNode * p1 =
- aData1 [p2->HashCode (nBuckets1)];
- while (p1) {
- if (p1->IsEqual(*p2))
+ const TColStd_intMapNode* p1 = theMap1.myData1[HashCode (aKeyInt, nBuckets1)];
+ while (p1)
+ {
+ if (p1->IsEqual(aKeyInt))
break;
- p1 = static_cast <const TColStd_intMapNode*> (p1->Next());
+ p1 = p1->Next();
}
// Add the block from the 2nd map only in the case when the similar
// block has not been found in the 1st map
- if (p1 == 0L) {
- if (Resizable()) {
- ReSize(InternalExtent());
- aData = (TColStd_intMapNode**) myData1;
+ if (p1 == 0L)
+ {
+ if (Resizable())
+ {
+ ReSize (myNbPackedMapNodes);
}
- const Standard_Integer aHashCode = p2->HashCode (NbBuckets());
- aData[aHashCode]= new TColStd_intMapNode (p2->Mask(), p2->Data(),
- aData[aHashCode]);
- Increment();
+ const Standard_Integer aHashCode = HashCode (aKeyInt, myNbBuckets);
+ myData1[aHashCode]= new TColStd_intMapNode (p2->Mask(), p2->Data(),
+ myData1[aHashCode]);
+ ++myNbPackedMapNodes;
myExtent += p2->NbValues();
}
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+ p2 = p2->Next();
}
}
}
Assign ( theMap );
return Standard_True;
}
- else {
- size_t aNewExtent (myExtent);
- TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
- const TColStd_intMapNode** aData2 =
- (const TColStd_intMapNode**) theMap.myData1;
- const Standard_Integer nBuckets2 = theMap.NbBuckets();
- // Iteration of the 2nd map.
- for (Standard_Integer i = 0; i <= nBuckets2; i++) {
- const TColStd_intMapNode * p2 = aData2[i];
- while (p2 != 0L) {
- // Find the corresponding block in the 1st (this) map
- Standard_Integer aHashCode = p2->HashCode (NbBuckets());
- TColStd_intMapNode * p1 = aData[aHashCode];
- while (p1) {
- if (p1->IsEqual(*p2)) {
- const size_t anOldPop = p1->NbValues();
- unsigned int newData = p1->Data() | p2->Data();
- if ( newData != p1->Data() ) {
- p1->ChangeData() = newData;
- aNewExtent = aNewExtent - anOldPop +
- TColStd_Population (p1->ChangeMask(), newData);
- }
- break;
+ size_t aNewExtent (myExtent);
+ const Standard_Integer nBuckets2 = theMap.myNbBuckets;
+
+ // Iteration of the 2nd map.
+ for (Standard_Integer i = 0; i <= nBuckets2; i++)
+ {
+ const TColStd_intMapNode* p2 = theMap.myData1[i];
+ while (p2 != 0L)
+ {
+ // Find aKey - the base address of currently iterated block of integers
+ const Standard_Integer aKey = p2->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
+ // Find the corresponding block in the 1st (this) map
+ Standard_Integer aHashCode = HashCode (aKeyInt, myNbBuckets);
+ TColStd_intMapNode* p1 = myData1[aHashCode];
+ while (p1)
+ {
+ if (p1->IsEqual(aKeyInt))
+ {
+ const size_t anOldPop = p1->NbValues();
+ unsigned int newData = p1->Data() | p2->Data();
+ if ( newData != p1->Data() ) {
+ p1->ChangeData() = newData;
+ aNewExtent = aNewExtent - anOldPop +
+ TColStd_Population (p1->ChangeMask(), newData);
}
- p1 = static_cast <TColStd_intMapNode*> (p1->Next());
+ break;
}
- // If the block is not found in the 1st map, add it to the 1st map
- if (p1 == 0L) {
- if (Resizable()) {
- ReSize(InternalExtent());
- aData = (TColStd_intMapNode**) myData1;
- aHashCode = p2->HashCode (NbBuckets());
- }
- aData[aHashCode] = new TColStd_intMapNode (p2->Mask(), p2->Data(),
- aData[aHashCode]);
- Increment();
- aNewExtent += p2->NbValues();
+ p1 = p1->Next();
+ }
+ // If the block is not found in the 1st map, add it to the 1st map
+ if (p1 == 0L)
+ {
+ if (Resizable())
+ {
+ ReSize (myNbPackedMapNodes);
+ aHashCode = HashCode (aKeyInt, myNbBuckets);
}
- p2 = static_cast <TColStd_intMapNode*> (p2->Next());
+ myData1[aHashCode] = new TColStd_intMapNode (p2->Mask(), p2->Data(),
+ myData1[aHashCode]);
+ ++myNbPackedMapNodes;
+ aNewExtent += p2->NbValues();
}
+ p2 = p2->Next();
}
- Standard_Boolean isChanged = ( myExtent != aNewExtent );
- myExtent = aNewExtent;
- return isChanged;
}
+ Standard_Boolean isChanged = ( myExtent != aNewExtent );
+ myExtent = aNewExtent;
+ return isChanged;
}
//=======================================================================
else if (myData1 == theMap2.myData1)
Intersect (theMap1);
else {
- const TColStd_intMapNode** aData1, ** aData2;
+ const TColStd_intMapNode* const* aData1;
+ const TColStd_intMapNode* const* aData2;
Standard_Integer nBuckets1, nBuckets2;
- if (theMap1.Extent() < theMap2.Extent()) {
- aData1 = (const TColStd_intMapNode**) theMap1.myData1;
- aData2 = (const TColStd_intMapNode**) theMap2.myData1;
- nBuckets1 = theMap1.NbBuckets();
- nBuckets2 = theMap2.NbBuckets();
- }
- else {
- aData1 = (const TColStd_intMapNode**) theMap2.myData1;
- aData2 = (const TColStd_intMapNode**) theMap1.myData1;
- nBuckets1 = theMap2.NbBuckets();
- nBuckets2 = theMap1.NbBuckets();
+ if (theMap1.Extent() < theMap2.Extent())
+ {
+ aData1 = theMap1.myData1;
+ aData2 = theMap2.myData1;
+ nBuckets1 = theMap1.myNbBuckets;
+ nBuckets2 = theMap2.myNbBuckets;
+ }
+ else
+ {
+ aData1 = theMap2.myData1;
+ aData2 = theMap1.myData1;
+ nBuckets1 = theMap2.myNbBuckets;
+ nBuckets2 = theMap1.myNbBuckets;
}
Clear();
- TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
+
// Iteration of the 1st map.
- for (Standard_Integer i = 0; i <= nBuckets1; i++) {
- const TColStd_intMapNode * p1 = aData1[i];
- while (p1 != 0L) {
+ for (Standard_Integer i = 0; i <= nBuckets1; i++)
+ {
+ const TColStd_intMapNode* p1 = aData1[i];
+ while (p1 != 0L)
+ {
+ // Find aKey - the base address of currently iterated block
+ const Standard_Integer aKey = p1->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
// Find the corresponding block in the 2nd map
- const TColStd_intMapNode * p2 =
- aData2 [p1->HashCode (nBuckets2)];
- while (p2) {
- if (p2->IsEqual(*p1)) {
+ const TColStd_intMapNode* p2 = aData2[HashCode (aKeyInt, nBuckets2)];
+ while (p2)
+ {
+ if (p2->IsEqual(aKeyInt))
+ {
const unsigned int aNewData = p1->Data() & p2->Data();
// Store the block - result of operation
- if (aNewData) {
- if (Resizable()) {
- ReSize(InternalExtent());
- aData = (TColStd_intMapNode**) myData1;
+ if (aNewData)
+ {
+ if (Resizable())
+ {
+ ReSize (myNbPackedMapNodes);
}
- const Standard_Integer aHashCode = p1->HashCode (NbBuckets());
+ const Standard_Integer aHashCode = HashCode (aKeyInt, myNbBuckets);
unsigned int aNewMask = p1->Mask();
myExtent += TColStd_Population (aNewMask, aNewData);
- aData[aHashCode]= new TColStd_intMapNode(aNewMask, aNewData,
- aData[aHashCode]);
- Increment();
+ myData1[aHashCode]= new TColStd_intMapNode(aNewMask, aNewData,
+ myData1[aHashCode]);
+ ++myNbPackedMapNodes;
}
break;
}
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+ p2 = p2->Next();
}
- p1 = static_cast <const TColStd_intMapNode*> (p1->Next());
+ p1 = p1->Next();
}
}
}
}
else if (myData1 == theMap.myData1) // A & A == A
return Standard_False;
- else {
- size_t aNewExtent (0);
- TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
- const TColStd_intMapNode** aData2 =
- (const TColStd_intMapNode**) theMap.myData1;
- const Standard_Integer nBuckets2 = theMap.NbBuckets();
- // Iteration of this map.
- for (Standard_Integer i = 0; i <= NbBuckets(); i++) {
- TColStd_intMapNode * q = 0L;
- TColStd_intMapNode * p1 = aData[i];
- while (p1 != 0L) {
- // Find the corresponding block in the 2nd map
- const TColStd_intMapNode * p2 =
- aData2 [p1->HashCode (nBuckets2)];
- while (p2) {
- if (p2->IsEqual(*p1)) {
- const unsigned int aNewData = p1->Data() & p2->Data();
- // Store the block - result of operation
- if (aNewData == 0)
- p2 = 0L; // no match - the block has to be removed
- else
- {
- if ( aNewData != p1->Data() )
- p1->ChangeData() = aNewData;
- aNewExtent += TColStd_Population (p1->ChangeMask(), aNewData);
- }
- break;
+ size_t aNewExtent (0);
+ const Standard_Integer nBuckets2 = theMap.myNbBuckets;
+
+ // Iteration of this map.
+ for (Standard_Integer i = 0; i <= myNbBuckets; i++)
+ {
+ TColStd_intMapNode* q = 0L;
+ TColStd_intMapNode* p1 = myData1[i];
+ while (p1 != 0L)
+ {
+ // Find aKey - the base address of currently iterated block of integers
+ const Standard_Integer aKey = p1->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
+ // Find the corresponding block in the 2nd map
+ const TColStd_intMapNode* p2 = theMap.myData1[HashCode (aKeyInt, nBuckets2)];
+ while (p2)
+ {
+ if (p2->IsEqual(aKeyInt))
+ {
+ const unsigned int aNewData = p1->Data() & p2->Data();
+ // Store the block - result of operation
+ if (aNewData == 0)
+ p2 = 0L; // no match - the block has to be removed
+ else
+ {
+ if ( aNewData != p1->Data() )
+ p1->ChangeData() = aNewData;
+ aNewExtent += TColStd_Population (p1->ChangeMask(), aNewData);
}
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+ break;
}
- TColStd_intMapNode* pNext = static_cast <TColStd_intMapNode*> (p1->Next());
- // If p2!=NULL, then the map node is kept and we move to the next one
- // Otherwise we should remove the current node
- if (p2)
- q = p1;
- else {
- Decrement();
- if (q) q->Next() = pNext;
- else aData[i] = pNext;
- delete p1;
- }
- p1 = pNext;
+ p2 = p2->Next();
+ }
+ TColStd_intMapNode* pNext = p1->Next();
+ // If p2!=NULL, then the map node is kept and we move to the next one
+ // Otherwise we should remove the current node
+ if (p2)
+ {
+ q = p1;
}
+ else
+ {
+ --myNbPackedMapNodes;
+ if (q) q->SetNext (pNext);
+ else myData1[i] = pNext;
+ delete p1;
+ }
+ p1 = pNext;
}
- Standard_Boolean isChanged = ( myExtent != aNewExtent );
- myExtent = aNewExtent;
- return isChanged;
}
+ Standard_Boolean isChanged = ( myExtent != aNewExtent );
+ myExtent = aNewExtent;
+ return isChanged;
}
//=======================================================================
Assign ( aMap );
}
else {
- const TColStd_intMapNode** aData1 =
- (const TColStd_intMapNode**) theMap1.myData1;
- const TColStd_intMapNode** aData2 =
- (const TColStd_intMapNode**) theMap2.myData1;
- const Standard_Integer nBuckets1 = theMap1.NbBuckets();
- const Standard_Integer nBuckets2 = theMap2.NbBuckets();
+ const Standard_Integer nBuckets1 = theMap1.myNbBuckets;
+ const Standard_Integer nBuckets2 = theMap2.myNbBuckets;
Clear();
- TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
+
// Iteration of the 1st map.
- for (Standard_Integer i = 0; i <= nBuckets1; i++) {
- const TColStd_intMapNode * p1 = aData1[i];
- while (p1 != 0L) {
+ for (Standard_Integer i = 0; i <= nBuckets1; i++)
+ {
+ const TColStd_intMapNode * p1 = theMap1.myData1[i];
+ while (p1 != 0L)
+ {
+ // Find aKey - the base address of currently iterated block of integers
+ const Standard_Integer aKey = p1->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
unsigned int aNewMask = p1->Mask();
unsigned int aNewData = p1->Data();
size_t nValues (p1->NbValues());
// Find the corresponding block in the 2nd map
- const TColStd_intMapNode * p2 =
- aData2 [p1->HashCode (nBuckets2)];
- while (p2) {
- if (p2->IsEqual(*p1)) {
+ const TColStd_intMapNode* p2 = theMap2.myData1[HashCode (aKeyInt, nBuckets2)];
+ while (p2)
+ {
+ if (p2->IsEqual(aKeyInt))
+ {
aNewData &= ~p2->Data();
nValues = TColStd_Population (aNewMask, aNewData);
break;
}
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+ p2 = p2->Next();
}
// Store the block - result of operation
- if (aNewData) {
- if (Resizable()) {
- ReSize(InternalExtent());
- aData = (TColStd_intMapNode**) myData1;
+ if (aNewData)
+ {
+ if (Resizable())
+ {
+ ReSize (myNbPackedMapNodes);
}
- const Standard_Integer aHashCode = p1->HashCode (NbBuckets());
- aData[aHashCode]= new TColStd_intMapNode (aNewMask, aNewData,
- aData[aHashCode]);
- Increment();
+ const Standard_Integer aHashCode = HashCode (aKeyInt, myNbBuckets);
+ myData1[aHashCode]= new TColStd_intMapNode (aNewMask, aNewData,
+ myData1[aHashCode]);
+ ++myNbPackedMapNodes;
myExtent += nValues;
}
- p1 = static_cast <const TColStd_intMapNode*> (p1->Next());
+ p1 = p1->Next();
}
}
}
}
else {
size_t aNewExtent (0);
- TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
- const TColStd_intMapNode** aData2 =
- (const TColStd_intMapNode**) theMap.myData1;
- const Standard_Integer nBuckets2 = theMap.NbBuckets();
+ const Standard_Integer nBuckets2 = theMap.myNbBuckets;
// Iteration of this map.
- for (Standard_Integer i = 0; i <= NbBuckets(); i++) {
- TColStd_intMapNode * q = 0L;
- TColStd_intMapNode * p1 = aData[i];
- while (p1 != 0L) {
- TColStd_intMapNode* pNext = static_cast <TColStd_intMapNode*> (p1->Next());
+ for (Standard_Integer i = 0; i <= myNbBuckets; i++)
+ {
+ TColStd_intMapNode* q = 0L;
+ TColStd_intMapNode* p1 = myData1[i];
+ while (p1 != 0L)
+ {
+ // Find aKey - the base address of currently iterated block of integers
+ const Standard_Integer aKey = p1->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
+ TColStd_intMapNode* pNext = p1->Next();
// Find the corresponding block in the 2nd map
- const TColStd_intMapNode * p2 =
- aData2 [p1->HashCode (nBuckets2)];
- while (p2) {
- if (p2->IsEqual(*p1)) {
+ const TColStd_intMapNode* p2 = theMap.myData1[HashCode (aKeyInt, nBuckets2)];
+ while (p2)
+ {
+ if (p2->IsEqual(aKeyInt))
+ {
const unsigned int aNewData = p1->Data() & ~p2->Data();
// Store the block - result of operation
- if (aNewData == 0) {
+ if (aNewData == 0)
+ {
// no match - the block has to be removed
- Decrement();
- if (q) q->Next() = pNext;
- else aData[i] = pNext;
+ --myNbPackedMapNodes;
+ if (q) q->SetNext (pNext);
+ else myData1[i] = pNext;
delete p1;
- }
- else if ( aNewData != p1->Data() ) {
+ }
+ else if ( aNewData != p1->Data() )
+ {
p1->ChangeData() = aNewData;
aNewExtent += TColStd_Population (p1->ChangeMask(), aNewData);
q = p1;
}
- else {
+ else
+ {
aNewExtent += p1->NbValues();
q = p1;
}
break;
}
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+ p2 = p2->Next();
}
- if (p2 == 0L) {
+ if (p2 == 0L)
+ {
aNewExtent += p1->NbValues();
q = p1;
}
Differ(theMap1);
else {
Standard_Integer i;
- const TColStd_intMapNode** aData1 =
- (const TColStd_intMapNode**) theMap1.myData1;
- const TColStd_intMapNode** aData2 =
- (const TColStd_intMapNode**) theMap2.myData1;
- const Standard_Integer nBuckets1 = theMap1.NbBuckets();
- const Standard_Integer nBuckets2 = theMap2.NbBuckets();
+ const Standard_Integer nBuckets1 = theMap1.myNbBuckets;
+ const Standard_Integer nBuckets2 = theMap2.myNbBuckets;
Clear();
- TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
// Iteration of the 1st map.
- for (i = 0; i <= nBuckets1; i++) {
- const TColStd_intMapNode * p1 = aData1[i];
- while (p1 != 0L) {
+ for (i = 0; i <= nBuckets1; i++)
+ {
+ const TColStd_intMapNode* p1 = theMap1.myData1[i];
+ while (p1 != 0L)
+ {
+ // Find aKey - the base address of currently iterated block of integers
+ const Standard_Integer aKey = p1->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
unsigned int aNewMask = p1->Mask();
unsigned int aNewData = p1->Data();
size_t nValues (p1->NbValues());
// Find the corresponding block in the 2nd map
- const TColStd_intMapNode * p2 =
- aData2 [p1->HashCode (nBuckets2)];
- while (p2) {
- if (p2->IsEqual(*p1)) {
+ const TColStd_intMapNode* p2 = theMap2.myData1[HashCode (aKeyInt, nBuckets2)];
+ while (p2)
+ {
+ if (p2->IsEqual(aKeyInt))
+ {
aNewData ^= p2->Data();
nValues = TColStd_Population (aNewMask, aNewData);
break;
}
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+ p2 = p2->Next();
}
// Store the block - result of operation
- if (aNewData) {
- if (Resizable()) {
- ReSize(InternalExtent());
- aData = (TColStd_intMapNode**) myData1;
+ if (aNewData)
+ {
+ if (Resizable())
+ {
+ ReSize (myNbPackedMapNodes);
}
- const Standard_Integer aHashCode = p1->HashCode (NbBuckets());
- aData[aHashCode]= new TColStd_intMapNode (aNewMask, aNewData,
- aData[aHashCode]);
- Increment();
+ const Standard_Integer aHashCode = HashCode (aKeyInt, myNbBuckets);
+ myData1[aHashCode]= new TColStd_intMapNode (aNewMask, aNewData,
+ myData1[aHashCode]);
+ ++myNbPackedMapNodes;
myExtent += nValues;
}
- p1 = static_cast <const TColStd_intMapNode*> (p1->Next());
+ p1 = p1->Next();
}
}
// Iteration of the 2nd map.
- for (i = 0; i <= nBuckets2; i++) {
- const TColStd_intMapNode * p2 = aData2[i];
- while (p2 != 0L) {
+ for (i = 0; i <= nBuckets2; i++)
+ {
+ const TColStd_intMapNode* p2 = theMap2.myData1[i];
+ while (p2 != 0L)
+ {
+ // Find aKey - the base address of currently iterated block
+ const Standard_Integer aKey = p2->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
// Find the corresponding block in the 1st map
- const TColStd_intMapNode * p1 =
- aData1 [p2->HashCode (nBuckets1)];
- while (p1) {
- if (p1->IsEqual(*p2))
+ const TColStd_intMapNode* p1 = theMap1.myData1[HashCode (aKeyInt, nBuckets1)];
+ while (p1)
+ {
+ if (p1->IsEqual(aKeyInt))
break;
- p1 = static_cast <const TColStd_intMapNode*> (p1->Next());
+ p1 = p1->Next();
}
// Add the block from the 2nd map only in the case when the similar
// block has not been found in the 1st map
- if (p1 == 0L) {
- if (Resizable()) {
- ReSize(InternalExtent());
- aData = (TColStd_intMapNode**) myData1;
+ if (p1 == 0L)
+ {
+ if (Resizable())
+ {
+ ReSize (myNbPackedMapNodes);
}
- const Standard_Integer aHashCode = p2->HashCode (NbBuckets());
- aData[aHashCode]= new TColStd_intMapNode (p2->Mask(), p2->Data(),
- aData[aHashCode]);
- Increment();
+ const Standard_Integer aHashCode = HashCode (aKeyInt, myNbBuckets);
+ myData1[aHashCode]= new TColStd_intMapNode (p2->Mask(), p2->Data(),
+ myData1[aHashCode]);
+ ++myNbPackedMapNodes;
myExtent += p2->NbValues();
}
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+ p2 = p2->Next();
}
}
}
Clear();
return Standard_True;
}
- else {
- size_t aNewExtent (0);
- TColStd_intMapNode** aData1 = (TColStd_intMapNode**) myData1;
- const TColStd_intMapNode** aData2 =
- (const TColStd_intMapNode**) theMap.myData1;
- const Standard_Integer nBuckets2 = theMap.NbBuckets();
- Standard_Boolean isChanged = Standard_False;
- Standard_Integer i = 0;
- // Iteration by other map
- for ( ; i <= nBuckets2; i++) {
- TColStd_intMapNode * q = 0L;
- const TColStd_intMapNode * p2 = aData2[i];
- while (p2 != 0L) {
- // Find the corresponding block in the 1st map
- TColStd_intMapNode * p1 =
- aData1[p2->HashCode (NbBuckets())];
- TColStd_intMapNode* pNext = static_cast <TColStd_intMapNode*> (p1->Next());
+
+ size_t aNewExtent (0);
+ const Standard_Integer nBuckets2 = theMap.myNbBuckets;
+ Standard_Boolean isChanged = Standard_False;
+ // Iteration by other map
+ for (Standard_Integer i = 0; i <= nBuckets2; i++)
+ {
+ TColStd_intMapNode * q = 0L;
+ const TColStd_intMapNode* p2 = theMap.myData1[i];
+ while (p2 != 0L)
+ {
+ // Find aKey - the base address of currently iterated block
+ const Standard_Integer aKey = p2->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
- while (p1) {
- if (p1->IsEqual(*p2)) {
- const unsigned int aNewData = p1->Data() ^ p2->Data();
- // Store the block - result of operation
- if (aNewData == 0) {
- // no match - the block has to be removed
- Decrement();
- if (q) q->Next() = pNext;
- else aData1[i] = pNext;
- delete p1;
- }
- else if ( aNewData != p1->Data() ) {
- p1->ChangeData() = aNewData;
- isChanged = Standard_True;
- aNewExtent += TColStd_Population (p1->ChangeMask(), aNewData);
- q = p1;
- }
- break;
+ // Find the corresponding block in the 1st map
+ TColStd_intMapNode* p1 = myData1[HashCode (aKeyInt, myNbBuckets)];
+ TColStd_intMapNode* pNext = p1->Next();
+ while (p1)
+ {
+ if (p1->IsEqual(aKeyInt))
+ {
+ const unsigned int aNewData = p1->Data() ^ p2->Data();
+ // Store the block - result of operation
+ if (aNewData == 0)
+ {
+ // no match - the block has to be removed
+ --myNbPackedMapNodes;
+ if (q) q->SetNext (pNext);
+ else myData1[i] = pNext;
+ delete p1;
}
- p1 = pNext;
- }
- // Add the block from the 2nd map only in the case when the similar
- // block has not been found in the 1st map
- TColStd_intMapNode** aData = NULL;
- if (p1 == 0L) {
- if (Resizable()) {
- ReSize(InternalExtent());
- aData = (TColStd_intMapNode**) myData1;
+ else if ( aNewData != p1->Data() )
+ {
+ p1->ChangeData() = aNewData;
+ isChanged = Standard_True;
+ aNewExtent += TColStd_Population (p1->ChangeMask(), aNewData);
+ q = p1;
}
- const Standard_Integer aHashCode = p2->HashCode (NbBuckets());
- aData[aHashCode]= new TColStd_intMapNode (p2->Mask(), p2->Data(),
- aData[aHashCode]);
- Increment();
- aNewExtent += p2->NbValues();
- isChanged = Standard_True;
+ break;
+ }
+ p1 = pNext;
+ }
+ // Add the block from the 2nd map only in the case when the similar
+ // block has not been found in the 1st map
+ if (p1 == 0L)
+ {
+ if (Resizable())
+ {
+ ReSize (myNbPackedMapNodes);
}
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+ const Standard_Integer aHashCode = HashCode (aKeyInt, myNbBuckets);
+ myData1[aHashCode] = new TColStd_intMapNode (p2->Mask(), p2->Data(),
+ myData1[aHashCode]);
+ ++myNbPackedMapNodes;
+ aNewExtent += p2->NbValues();
+ isChanged = Standard_True;
}
+ p2 = p2->Next();
}
- myExtent = aNewExtent;
- return isChanged;
}
+ myExtent = aNewExtent;
+ return isChanged;
}
//=======================================================================
return Standard_True;
else if ( Extent() != theMap.Extent() )
return Standard_False;
- else {
- const TColStd_intMapNode** aData1 = (const TColStd_intMapNode**) myData1;
- const TColStd_intMapNode** aData2 = (const TColStd_intMapNode**) theMap.myData1;
- const Standard_Integer nBuckets2 = theMap.NbBuckets();
- if(aData1 == aData2)
- return Standard_True;
-
- Standard_Integer i = 0;
- // Iteration of this map.
- for (; i <= NbBuckets(); i++) {
- const TColStd_intMapNode * p1 = aData1[i];
- while (p1 != 0L) {
- TColStd_intMapNode* pNext = static_cast <TColStd_intMapNode*> (p1->Next());
- // Find the corresponding block in the 2nd map
- const TColStd_intMapNode * p2 =
- aData2 [p1->HashCode (nBuckets2)];
- while (p2) {
- if ( p2->IsEqual(*p1) ) {
- if ( p1->Data() != p2->Data() )
- return Standard_False;
- break;
- }
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+ else if(myData1 == theMap.myData1)
+ return Standard_True;
+
+ const Standard_Integer nBuckets2 = theMap.myNbBuckets;
+ // Iteration of this map.
+ for (Standard_Integer i = 0; i <= myNbBuckets; i++)
+ {
+ const TColStd_intMapNode* p1 = myData1[i];
+ while (p1 != 0L)
+ {
+ // Find aKey - the base address of currently iterated block of integers
+ const Standard_Integer aKey = p1->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
+ TColStd_intMapNode* pNext = p1->Next();
+ // Find the corresponding block in the 2nd map
+ const TColStd_intMapNode* p2 = theMap.myData1[HashCode (aKeyInt, nBuckets2)];
+ while (p2)
+ {
+ if ( p2->IsEqual(aKeyInt) )
+ {
+ if ( p1->Data() != p2->Data() )
+ return Standard_False;
+ break;
}
- // if the same block not found, maps are different
- if (p2 == 0L)
- return Standard_False;
-
- p1 = pNext;
+ p2 = p2->Next();
}
+ // if the same block not found, maps are different
+ if (p2 == 0L)
+ return Standard_False;
+
+ p1 = pNext;
}
- return Standard_True;
}
+ return Standard_True;
}
//=======================================================================
return Standard_False;
else if ( Extent() > theMap.Extent() )
return Standard_False;
- else {
- const TColStd_intMapNode** aData1 = (const TColStd_intMapNode**) myData1;
- const TColStd_intMapNode** aData2 = (const TColStd_intMapNode**) theMap.myData1;
- if(aData1 == aData2)
- return Standard_True;
- const Standard_Integer nBuckets2 = theMap.NbBuckets();
-
- Standard_Integer i = 0;
- // Iteration of this map.
- for (; i <= NbBuckets(); i++) {
- const TColStd_intMapNode * p1 = aData1[i];
- while (p1 != 0L) {
- TColStd_intMapNode* pNext = static_cast <TColStd_intMapNode*> (p1->Next());
- // Find the corresponding block in the 2nd map
- const TColStd_intMapNode * p2 =
- aData2 [p1->HashCode (nBuckets2)];
- if (!p2)
- return Standard_False;
- while (p2) {
- if ( p2->IsEqual(*p1) ) {
- if ( p1->Data() & ~p2->Data() ) // at least one bit set in p1 is not set in p2
- return Standard_False;
- break;
- }
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+ else if(myData1 == theMap.myData1)
+ return Standard_True;
+
+ const Standard_Integer nBuckets2 = theMap.myNbBuckets;
+ // Iteration of this map.
+ for (Standard_Integer i = 0; i <= myNbBuckets; i++)
+ {
+ const TColStd_intMapNode* p1 = myData1[i];
+ while (p1 != 0L)
+ {
+ // Find aKey - the base address of currently iterated block of integers
+ const Standard_Integer aKey = p1->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
+ TColStd_intMapNode* pNext = p1->Next();
+ // Find the corresponding block in the 2nd map
+ const TColStd_intMapNode* p2 = theMap.myData1[HashCode (aKeyInt, nBuckets2)];
+ if (!p2)
+ return Standard_False;
+ while (p2)
+ {
+ if ( p2->IsEqual(aKeyInt) )
+ {
+ if ( p1->Data() & ~p2->Data() ) // at least one bit set in p1 is not set in p2
+ return Standard_False;
+ break;
}
- p1 = pNext;
+ p2 = p2->Next();
}
+ p1 = pNext;
}
- return Standard_True;
}
+ return Standard_True;
}
//=======================================================================
{
if (IsEmpty() || theMap.IsEmpty()) // A * 0 == 0 * B == 0
return Standard_False;
- else {
- const TColStd_intMapNode** aData1 = (const TColStd_intMapNode**) myData1;
- const TColStd_intMapNode** aData2 = (const TColStd_intMapNode**) theMap.myData1;
- const Standard_Integer nBuckets2 = theMap.NbBuckets();
- if(aData1 == aData2)
- return Standard_True;
-
- Standard_Integer i = 0;
- // Iteration of this map.
- for (; i <= NbBuckets(); i++) {
- const TColStd_intMapNode * p1 = aData1[i];
- while (p1 != 0L) {
- TColStd_intMapNode* pNext = static_cast <TColStd_intMapNode*> (p1->Next());
- // Find the corresponding block in the 2nd map
- const TColStd_intMapNode * p2 =
- aData2 [p1->HashCode (nBuckets2)];
- while (p2) {
- if (p2->IsEqual(*p1)) {
- if ( p1->Data() & p2->Data() )
- return Standard_True;
- break;
- }
- p2 = static_cast <const TColStd_intMapNode*> (p2->Next());
+
+ if(myData1 == theMap.myData1)
+ return Standard_True;
+
+ const Standard_Integer nBuckets2 = theMap.myNbBuckets;
+ // Iteration of this map.
+ for (Standard_Integer i = 0; i <= myNbBuckets; i++)
+ {
+ const TColStd_intMapNode* p1 = myData1[i];
+ while (p1 != 0L) {
+ // Find aKey - the base address of currently iterated block of integers
+ const Standard_Integer aKey = p1->Key();
+ const Standard_Integer aKeyInt = packedKeyIndex (aKey);
+ TColStd_intMapNode* pNext = p1->Next();
+ // Find the corresponding block in the 2nd map
+ const TColStd_intMapNode* p2 = theMap.myData1[HashCode (aKeyInt, nBuckets2)];
+ while (p2)
+ {
+ if (p2->IsEqual(aKeyInt))
+ {
+ if (p1->Data() & p2->Data())
+ return Standard_True;
+ break;
}
- p1 = pNext;
+ p2 = p2->Next();
}
+ p1 = pNext;
}
- return Standard_False;
}
+ return Standard_False;
+}
+
+//=======================================================================
+//function : Statistics
+//purpose :
+//=======================================================================
+void TColStd_PackedMapOfInteger::Statistics (Standard_OStream& theStream) const
+{
+ theStream << "\nMap Statistics\n---------------\n\n";
+ theStream << "This Map has " << myNbBuckets << " Buckets and " << myNbPackedMapNodes << " Keys\n\n";
+ if (myNbPackedMapNodes == 0)
+ {
+ return;
+ }
+
+ NCollection_Array1<Standard_Integer> aSizes (0, myNbPackedMapNodes);
+ aSizes.Init (0);
+
+ theStream << "\nStatistics for the first Key\n";
+ Standard_Integer aNbNonEmpty = 0;
+ for (Standard_Integer aBucketIter = 0; aBucketIter <= myNbBuckets; ++aBucketIter)
+ {
+ TColStd_intMapNode* aSubNodeIter = myData1[aBucketIter];
+ if (aSubNodeIter != NULL)
+ {
+ ++aNbNonEmpty;
+ }
+
+ Standard_Integer aNbMapSubNodes = 0;
+ for (; aSubNodeIter != NULL; aSubNodeIter = aSubNodeIter->Next())
+ {
+ ++aNbMapSubNodes;
+ }
+ ++aSizes[aNbMapSubNodes];
+ }
+
+ // display results
+ Standard_Integer aNbMapSubNodesTotal = 0;
+ for (Standard_Integer aNbMapSubNodes = 0; aNbMapSubNodes <= myNbPackedMapNodes; ++aNbMapSubNodes)
+ {
+ if (aSizes[aNbMapSubNodes] > 0)
+ {
+ aNbMapSubNodesTotal += aSizes[aNbMapSubNodes] * aNbMapSubNodes;
+ theStream << std::setw(5) << aSizes[aNbMapSubNodes] << " buckets of size " << aNbMapSubNodes << "\n";
+ }
+ }
+
+ const Standard_Real aMean = ((Standard_Real) aNbMapSubNodesTotal) / ((Standard_Real) aNbNonEmpty);
+ theStream << "\n\nMean of length: " << aMean << "\n";
}
#ifndef TColStd_PackedMapOfInteger_HeaderFile
#define TColStd_PackedMapOfInteger_HeaderFile
+#include <Standard.hxx>
+#include <Standard_Address.hxx>
+#include <Standard_Boolean.hxx>
#include <Standard_DefineAlloc.hxx>
+#include <Standard_Integer.hxx>
#include <Standard_NoSuchObject.hxx>
-#include <TCollection_BasicMap.hxx>
-#include <TCollection_BasicMapIterator.hxx>
+#include <Standard_OStream.hxx>
+#include <Standard_Handle.hxx>
/**
* Optimized Map of integer values. Each block of 32 integers is stored in 8 bytes in memory.
*/
-class TColStd_PackedMapOfInteger : private TCollection_BasicMap
+class TColStd_PackedMapOfInteger
{
- public:
- // operators new and delete must be defined explicitly
- // since inherited ones are not accessible
+public:
DEFINE_STANDARD_ALLOC
+private:
+
+ //! 5 lower bits
+ static const unsigned int MASK_LOW = 0x001f;
+
+ //! 27 upper bits
+ static const unsigned int MASK_HIGH = ~MASK_LOW;
+
+ //! Class implementing a block of 32 consecutive integer values as a node of a Map collection.
+ //! The data are stored in 64 bits as:
+ //! - bits 0 - 4 : (number of integers stored in the block) - 1;
+ //! - bits 5 - 31: base address of the block of integers (low bits assumed 0)
+ //! - bits 32 - 63: 32-bit field where each bit indicates the presence of the corresponding integer in the block.
+ //! Number of non-zero bits must be equal to the number expressed in bits 0-4.
+ class TColStd_intMapNode
+ {
+ public:
+ TColStd_intMapNode (TColStd_intMapNode* thePtr = NULL)
+ : myNext (thePtr), myMask (0), myData (0) {}
+
+ TColStd_intMapNode (Standard_Integer theValue, TColStd_intMapNode*& thePtr)
+ : myNext (thePtr),
+ myMask ((unsigned int) (theValue & MASK_HIGH)),
+ myData (1 << (theValue & MASK_LOW)) {}
+
+ TColStd_intMapNode (unsigned int theMask, unsigned int theData, TColStd_intMapNode* thePtr)
+ : myNext (thePtr),
+ myMask (theMask),
+ myData (theData) {}
+
+ unsigned int Mask() const { return myMask; }
+
+ unsigned int Data() const { return myData; }
+
+ unsigned int& ChangeMask() { return myMask; }
+
+ unsigned int& ChangeData() { return myData; }
+
+ //! Compute the sequential index of this packed node in the map.
+ Standard_Integer Key() const { return Standard_Integer (myMask & MASK_HIGH); }
+
+ //! Return the number of set integer keys.
+ size_t NbValues() const { return size_t(myMask & MASK_LOW) + 1; }
+
+ //! Return TRUE if this packed node is not empty.
+ Standard_Boolean HasValues() const { return (myData != 0); }
+
+ //! Return TRUE if the given integer key is set within this packed node.
+ Standard_Integer HasValue (Standard_Integer theValue) const { return (myData & (1 << (theValue & MASK_LOW))); }
+
+ //! Add integer key to this packed node.
+ //! @return TRUE if key has been added
+ Standard_Boolean AddValue (Standard_Integer theValue)
+ {
+ const Standard_Integer aValInt = (1 << (theValue & MASK_LOW));
+ if ((myData & aValInt) == 0)
+ {
+ myData ^= aValInt;
+ ++myMask;
+ return Standard_True;
+ }
+ return Standard_False;
+ }
+
+ //! Delete integer key from this packed node.
+ //! @return TRUE if key has been deleted
+ Standard_Boolean DelValue (Standard_Integer theValue)
+ {
+ const Standard_Integer aValInt = (1 << (theValue & MASK_LOW));
+ if ((myData & aValInt) != 0)
+ {
+ myData ^= aValInt;
+ myMask--;
+ return Standard_True;
+ }
+ return Standard_False;
+ }
+
+ //! Find the smallest non-zero bit under the given mask. Outputs the new mask
+ //! that does not contain the detected bit.
+ Standard_Integer FindNext (unsigned int& theMask) const;
+
+ //! Return the next node having the same hash code.
+ TColStd_intMapNode* Next() const { return myNext; }
+
+ //! Set the next node having the same hash code.
+ void SetNext (TColStd_intMapNode* theNext) { myNext = theNext; }
+
+ public:
+ //! Support of Map interface.
+ Standard_Integer HashCode (Standard_Integer theUpper) const
+ {
+ return ::HashCode (Standard_Integer(myMask >> 5), theUpper);
+ }
+
+ //! Support of Map interface.
+ Standard_Boolean IsEqual (Standard_Integer theOther) const
+ {
+ return ((myMask >> 5) == (unsigned)theOther);
+ }
+
+ private:
+ TColStd_intMapNode* myNext;
+ unsigned int myMask;
+ unsigned int myData;
+ };
+
public:
//! Iterator of class TColStd_PackedMapOfInteger.
- class Iterator : public TCollection_BasicMapIterator
+ class Iterator
{
public:
/// Empty Constructor.
- Iterator() : myIntMask (~0U), myKey (0) {}
+ Iterator()
+ : myBuckets (NULL),
+ myNode (NULL),
+ myNbBuckets (-1),
+ myBucket (-1),
+ myIntMask (~0U),
+ myKey (0) {}
/// Constructor.
Iterator (const TColStd_PackedMapOfInteger& theMap)
- : TCollection_BasicMapIterator (theMap),
+ : myBuckets (theMap.myData1),
+ myNode (NULL),
+ myNbBuckets (theMap.myData1 != NULL ? theMap.myNbBuckets : -1),
+ myBucket (-1),
myIntMask (~0U)
{
+ next();
myKey = myNode != NULL ? TColStd_intMapNode_findNext (myNode, myIntMask) : 0;
}
//! Re-initialize with the same or another Map instance.
void Initialize (const TColStd_PackedMapOfInteger& theMap)
{
- TCollection_BasicMapIterator::Initialize (theMap);
+ myBuckets = theMap.myData1;
+ myBucket = -1;
+ myNode = NULL;
+ myNbBuckets = theMap.myData1 != NULL ? theMap.myNbBuckets : -1;
+ next();
+
myIntMask = ~0U;
myKey = myNode != NULL ? TColStd_intMapNode_findNext (myNode, myIntMask) : 0;
}
//! Restart the iteration
void Reset()
{
- TCollection_BasicMapIterator::Reset();
+ myBucket = -1;
+ myNode = NULL;
+ next();
+
myIntMask = ~0U;
myKey = myNode != NULL ? TColStd_intMapNode_findNext (myNode, myIntMask) : 0;
}
return myKey;
}
+ //! Return TRUE if iterator points to the node.
+ Standard_Boolean More() const { return myNode != NULL; }
+
//! Increment the iterator
void Next()
{
- for (; myNode != NULL; TCollection_BasicMapIterator::Next())
+ for (; myNode != NULL; next())
{
myKey = TColStd_intMapNode_findNext (myNode, myIntMask);
if (myIntMask != ~0u)
}
}
}
+ private:
+ //! Go to the next bucket in the map.
+ void next()
+ {
+ if (myBuckets == NULL)
+ {
+ return;
+ }
+
+ if (myNode != NULL)
+ {
+ myNode = myNode->Next();
+ }
+
+ while (myNode == NULL)
+ {
+ ++myBucket;
+ if (myBucket > myNbBuckets)
+ {
+ return;
+ }
+ myNode = myBuckets[myBucket];
+ }
+ }
private:
+ TColStd_intMapNode** myBuckets;
+ TColStd_intMapNode* myNode;
+ Standard_Integer myNbBuckets;
+ Standard_Integer myBucket;
+
unsigned int myIntMask; //!< all bits set above the iterated position
Standard_Integer myKey; //!< Currently iterated key
};
public:
- /// Constructor
- inline TColStd_PackedMapOfInteger (const Standard_Integer NbBuckets = 1)
- : TCollection_BasicMap (NbBuckets, Standard_True),
- myExtent (0) {}
-
- /// Copy constructor
- inline TColStd_PackedMapOfInteger (const TColStd_PackedMapOfInteger& theOther)
- : TCollection_BasicMap (1, Standard_True),
- myExtent (0)
- { Assign(theOther); }
+ //! Constructor
+ TColStd_PackedMapOfInteger (const Standard_Integer theNbBuckets = 1)
+ : myData1 (NULL),
+ myNbBuckets (theNbBuckets),
+ myNbPackedMapNodes (0),
+ myExtent (0) {}
+
+ //! Copy constructor
+ TColStd_PackedMapOfInteger (const TColStd_PackedMapOfInteger& theOther)
+ : myData1 (NULL),
+ myNbBuckets (1),
+ myNbPackedMapNodes (0),
+ myExtent (0)
+ {
+ Assign (theOther);
+ }
inline TColStd_PackedMapOfInteger&
operator = (const TColStd_PackedMapOfInteger& Other)
Standard_EXPORT Standard_Boolean
Remove (const Standard_Integer aKey);
- inline Standard_Integer NbBuckets () const
- { return TCollection_BasicMap::NbBuckets(); }
-
- inline Standard_Integer Extent () const
- { return Standard_Integer (myExtent); }
+ //! Returns the number of map buckets (not that since integers are packed in this map, the number is smaller than extent).
+ Standard_Integer NbBuckets() const { return myNbBuckets; }
- inline Standard_Boolean IsEmpty () const
- { return TCollection_BasicMap::IsEmpty(); }
+ //! Returns map extent.
+ Standard_Integer Extent() const { return Standard_Integer (myExtent); }
- inline void Statistics (Standard_OStream& outStream) const
- { TCollection_BasicMap::Statistics (outStream); }
+ //! Returns TRUE if map is empty.
+ Standard_Boolean IsEmpty() const { return myNbPackedMapNodes == 0; }
/**
* Query the minimal contained key value.
*/
Standard_EXPORT Standard_Integer GetMaximalMapped () const;
+ //! Prints useful statistics about the map.
+ //! It can be used to test the quality of the hashcoding.
+ Standard_EXPORT void Statistics (Standard_OStream& theStream) const;
+
public:
//!@name Boolean operations with maps as sets of integers
//!@{
//!@}
protected:
- // ---------- PROTECTED METHODS ----------
- inline Standard_Integer InternalExtent () const
- { return TCollection_BasicMap::Extent(); }
-private:
+ //! Returns TRUE if resizing the map should be considered.
+ Standard_Boolean Resizable() const { return IsEmpty() || (myNbPackedMapNodes > myNbBuckets); }
- //! Class implementing a block of 32 consecutive integer values as a node of a Map collection.
- //! The data are stored in 64 bits as:
- //! - bits 0 - 4 : (number of integers stored in the block) - 1;
- //! - bits 5 - 31: base address of the block of integers (low bits assumed 0)
- //! - bits 32 - 63: 32-bit field where each bit indicates the presence of the corresponding integer in the block.
- //! Number of non-zero bits must be equal to the number expressed in bits 0-4.
- class TColStd_intMapNode;
+ //! Return an integer index for specified key.
+ static Standard_Integer packedKeyIndex (Standard_Integer theKey) { return (unsigned)theKey >> 5; }
+
+private:
//! Find the smallest non-zero bit under the given mask.
//! Outputs the new mask that does not contain the detected bit.
Standard_EXPORT static Standard_Integer TColStd_intMapNode_findPrev (const Standard_Address theNode,
unsigned int& theMask);
+ //! Compute the population (i.e., the number of non-zero bits) of the 32-bit word theData.
+ //! The population is stored decremented as it is defined in TColStd_intMapNode.
+ //! Source: H.S.Warren, Hacker's Delight, Addison-Wesley Inc. 2002, Ch.5.1
+ static size_t TColStd_Population (unsigned int& theMask, unsigned int theData)
+ {
+ unsigned int aRes = theData - ((theData>>1) & 0x55555555);
+ aRes = (aRes & 0x33333333) + ((aRes>>2) & 0x33333333);
+ aRes = (aRes + (aRes>>4)) & 0x0f0f0f0f;
+ aRes = aRes + (aRes>>8);
+ aRes = aRes + (aRes>>16);
+ theMask = (theMask & TColStd_PackedMapOfInteger::MASK_HIGH) | ((aRes - 1) & TColStd_PackedMapOfInteger::MASK_LOW);
+ return size_t(aRes & 0x3f);
+ }
+
private:
- size_t myExtent;
+
+ TColStd_intMapNode** myData1; //!< data array
+ Standard_Integer myNbBuckets; //!< number of buckets (size of data array)
+ Standard_Integer myNbPackedMapNodes; //!< amount of packed map nodes
+ Standard_Size myExtent; //!< extent of this map (number of unpacked integer keys)
};
#endif