1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

0031943: Foundation Classes, TColStd_PackedMapOfInteger - get rid of TCollection_BasicMap

TCollection_BasicMap has been merged into TColStd_PackedMapOfInteger.
TColStd_PackedMapOfInteger has been cleaned up from redundant type casts.
This commit is contained in:
kgv 2018-09-26 17:10:30 +03:00 committed by bugmaster
parent 6e01c25ad1
commit d99673cf22
2 changed files with 854 additions and 740 deletions

File diff suppressed because it is too large Load Diff

View File

@ -16,43 +16,167 @@
#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) {}
//! Constructor
TColStd_PackedMapOfInteger (const Standard_Integer theNbBuckets = 1)
: myData1 (NULL),
myNbBuckets (theNbBuckets),
myNbPackedMapNodes (0),
myExtent (0) {}
/// Copy constructor
inline TColStd_PackedMapOfInteger (const TColStd_PackedMapOfInteger& theOther)
: TCollection_BasicMap (1, Standard_True),
myExtent (0)
{ Assign(theOther); }
//! 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(); }
//! 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_Integer Extent () const
{ return Standard_Integer (myExtent); }
//! Returns map extent.
Standard_Integer Extent() const { return Standard_Integer (myExtent); }
inline Standard_Boolean IsEmpty () const
{ return TCollection_BasicMap::IsEmpty(); }
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,20 +436,15 @@ public:
//!@}
protected:
// ---------- PROTECTED METHODS ----------
inline Standard_Integer InternalExtent () const
{ return TCollection_BasicMap::Extent(); }
//! Returns TRUE if resizing the map should be considered.
Standard_Boolean Resizable() const { return IsEmpty() || (myNbPackedMapNodes > myNbBuckets); }
//! Return an integer index for specified key.
static Standard_Integer packedKeyIndex (Standard_Integer theKey) { return (unsigned)theKey >> 5; }
private:
//! 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;
//! 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_findNext (const Standard_Address theNode,
@ -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