]> OCCT Git - occt.git/commitdiff
0031943: Foundation Classes, TColStd_PackedMapOfInteger - get rid of TCollection_BasicMap
authorkgv <kgv@opencascade.com>
Wed, 26 Sep 2018 14:10:30 +0000 (17:10 +0300)
committerbugmaster <bugmaster@opencascade.com>
Sat, 21 Nov 2020 09:19:48 +0000 (12:19 +0300)
TCollection_BasicMap has been merged into TColStd_PackedMapOfInteger.
TColStd_PackedMapOfInteger has been cleaned up from redundant type casts.

src/TColStd/TColStd_PackedMapOfInteger.cxx
src/TColStd/TColStd_PackedMapOfInteger.hxx

index 6dbc311cd81e9ee67acee1294722e33afb6b5bd4..7ac90c53b4140e41c2fab2c1eb7c0b67a19cf57f 100644 (file)
 
 #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  :
@@ -306,20 +116,17 @@ TColStd_PackedMapOfInteger& TColStd_PackedMapOfInteger::Assign
   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);
@@ -336,34 +143,39 @@ TColStd_PackedMapOfInteger& TColStd_PackedMapOfInteger::Assign
 //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;
 }
 
 //=======================================================================
@@ -373,23 +185,25 @@ void TColStd_PackedMapOfInteger::ReSize (const Standard_Integer nbBuckets)
 
 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;
 }
 
@@ -401,30 +215,30 @@ void TColStd_PackedMapOfInteger::Clear ()
 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;
 }
 
 //=======================================================================
@@ -435,17 +249,21 @@ Standard_Boolean TColStd_PackedMapOfInteger::Add (const Standard_Integer aKey)
 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;
 }
@@ -457,30 +275,42 @@ Standard_Boolean TColStd_PackedMapOfInteger::Contains
 
 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;
 }
@@ -492,23 +322,29 @@ Standard_Boolean TColStd_PackedMapOfInteger::Remove(const Standard_Integer aKey)
 
 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;
 }
@@ -520,23 +356,29 @@ Standard_Integer TColStd_PackedMapOfInteger::GetMinimalMapped () const
 
 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;
 }
@@ -558,72 +400,73 @@ void TColStd_PackedMapOfInteger::Union (const TColStd_PackedMapOfInteger& theMap
   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();
       }
     }
   }
@@ -642,52 +485,56 @@ Standard_Boolean TColStd_PackedMapOfInteger::Unite(const TColStd_PackedMapOfInte
     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;
 }
 
 //=======================================================================
@@ -706,50 +553,60 @@ void TColStd_PackedMapOfInteger::Intersection
   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();
       }
     }
   }
@@ -771,55 +628,60 @@ Standard_Boolean TColStd_PackedMapOfInteger::Intersect
   }
   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;
 }
 
 //=======================================================================
@@ -843,45 +705,48 @@ void TColStd_PackedMapOfInteger::Subtraction
     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();
       }
     }
   }
@@ -903,44 +768,51 @@ Standard_Boolean TColStd_PackedMapOfInteger::Subtract
   }
   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;
         }
@@ -971,75 +843,83 @@ void TColStd_PackedMapOfInteger::Difference  (const TColStd_PackedMapOfInteger&
     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();
       }
     }
   }
@@ -1062,66 +942,69 @@ Standard_Boolean TColStd_PackedMapOfInteger::Differ(const TColStd_PackedMapOfInt
     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;
 }
 
 //=======================================================================
@@ -1135,39 +1018,40 @@ Standard_Boolean TColStd_PackedMapOfInteger::IsEqual(const TColStd_PackedMapOfIn
     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;
 }
 
 //=======================================================================
@@ -1183,37 +1067,38 @@ Standard_Boolean TColStd_PackedMapOfInteger::IsSubset (const TColStd_PackedMapOf
     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;
 }
 
 //=======================================================================
@@ -1225,33 +1110,83 @@ Standard_Boolean TColStd_PackedMapOfInteger::HasIntersection (const TColStd_Pack
 {
   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";
 }
index 0baa0f6aa31b4ee29351faac8c2e7309bb30a3e0..c8dd276544076f00bc0f046af74a0e6f9b583cb0 100644 (file)
 #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;
     }
@@ -60,7 +184,10 @@ public:
     //! Restart the iteration
     void Reset()
     {
-      TCollection_BasicMapIterator::Reset();
+      myBucket = -1;
+      myNode = NULL;
+      next();
+
       myIntMask = ~0U;
       myKey = myNode != NULL ? TColStd_intMapNode_findNext (myNode, myIntMask) : 0;
     }
@@ -72,10 +199,13 @@ public:
       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)
@@ -84,24 +214,59 @@ public:
         }
       }
     }
+  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) 
@@ -119,17 +284,14 @@ public:
   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.
@@ -141,6 +303,10 @@ public:
    */
   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
   //!@{
@@ -270,19 +436,14 @@ public:
   //!@}
   
  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.
@@ -294,8 +455,26 @@ private:
   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