Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-21 09:17:57

0001 // Copyright (c) 2005-2026 OPEN CASCADE SAS
0002 //
0003 // This file is part of Open CASCADE Technology software library.
0004 //
0005 // This library is free software; you can redistribute it and/or modify it under
0006 // the terms of the GNU Lesser General Public License version 2.1 as published
0007 // by the Free Software Foundation, with special exception defined in the file
0008 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0009 // distribution for complete text of the license and disclaimer of any warranty.
0010 //
0011 // Alternatively, this file may be used under the terms of Open CASCADE
0012 // commercial license or contractual agreement.
0013 
0014 #ifndef NCollection_PackedMap_HeaderFile
0015 #define NCollection_PackedMap_HeaderFile
0016 
0017 #include <Standard.hxx>
0018 #include <Standard_DefineAlloc.hxx>
0019 #include <Standard_NoSuchObject.hxx>
0020 #include <Standard_OStream.hxx>
0021 #include <NCollection_Array1.hxx>
0022 #include <NCollection_Primes.hxx>
0023 
0024 #include <cstdint>
0025 #include <cstring>
0026 #include <type_traits>
0027 
0028 //! @brief Optimized Map for integer values of various integral types.
0029 //!
0030 //! This template class provides a memory-efficient storage for sets of integers.
0031 //! Each block of BitsPerBlock (32 or 64) consecutive integers is stored compactly
0032 //! using bit manipulation. The block size is automatically selected based on
0033 //! the integer type: 32 bits for int/unsigned, 64 bits for int64_t/size_t.
0034 //!
0035 //! @tparam IntType The integral type to store (int, unsigned int, int64_t, size_t, etc.)
0036 template <typename IntType>
0037 class NCollection_PackedMap
0038 {
0039   static_assert(std::is_integral<IntType>::value,
0040                 "NCollection_PackedMap requires an integral type");
0041 
0042 public:
0043   DEFINE_STANDARD_ALLOC
0044 
0045   //! True if the integer type is larger than 32 bits
0046   static constexpr bool Is64Bit = sizeof(IntType) > 4;
0047 
0048   //! The block type for storing packed bits
0049   using BlockType = typename std::conditional<Is64Bit, uint64_t, uint32_t>::type;
0050 
0051   //! The index type for addressing blocks
0052   using IndexType = typename std::conditional<sizeof(IntType) <= 4, uint32_t, uint64_t>::type;
0053 
0054   //! Number of bits per block
0055   static constexpr int BitsPerBlock = Is64Bit ? 64 : 32;
0056 
0057 private:
0058   //! Number of low bits used for position within a block
0059   static constexpr int MaskLowBits = Is64Bit ? 6 : 5;
0060 
0061   //! Mask for low bits (position within block)
0062   static constexpr IndexType MASK_LOW = (IndexType(1) << MaskLowBits) - 1;
0063 
0064   //! Mask for high bits (block base address)
0065   static constexpr IndexType MASK_HIGH = ~MASK_LOW;
0066 
0067   //! @brief Class implementing a block of consecutive integer values as a node.
0068   //!
0069   //! For 32-bit types: stores 32 consecutive values
0070   //! For 64-bit types: stores 64 consecutive values
0071   //!
0072   //! The data are stored as:
0073   //! - myMask: contains the count-1 in low bits and block base address in high bits
0074   //! - myData: bit field where each bit indicates presence of corresponding integer
0075   class PackedMapNode
0076   {
0077   public:
0078     PackedMapNode(PackedMapNode* thePtr = nullptr)
0079         : myNext(thePtr),
0080           myMask(0),
0081           myData(0)
0082     {
0083     }
0084 
0085     PackedMapNode(IntType theValue, PackedMapNode*& thePtr)
0086         : myNext(thePtr),
0087           myMask(static_cast<IndexType>(theValue) & MASK_HIGH),
0088           myData(BlockType(1) << (static_cast<IndexType>(theValue) & MASK_LOW))
0089     {
0090     }
0091 
0092     PackedMapNode(IndexType theMask, BlockType theData, PackedMapNode* thePtr)
0093         : myNext(thePtr),
0094           myMask(theMask),
0095           myData(theData)
0096     {
0097     }
0098 
0099     IndexType Mask() const { return myMask; }
0100 
0101     BlockType Data() const { return myData; }
0102 
0103     IndexType& ChangeMask() { return myMask; }
0104 
0105     BlockType& ChangeData() { return myData; }
0106 
0107     //! Compute the sequential index of this packed node in the map.
0108     IntType Key() const { return static_cast<IntType>(myMask & MASK_HIGH); }
0109 
0110     //! Return the number of set integer keys.
0111     size_t NbValues() const { return size_t(myMask & MASK_LOW) + 1; }
0112 
0113     //! Return TRUE if this packed node is not empty.
0114     bool HasValues() const { return (myData != 0); }
0115 
0116     //! Return TRUE if the given integer key is set within this packed node.
0117     bool HasValue(IntType theValue) const
0118     {
0119       return (myData & (BlockType(1) << (static_cast<IndexType>(theValue) & MASK_LOW))) != 0;
0120     }
0121 
0122     //! Add integer key to this packed node.
0123     //! @return TRUE if key has been added
0124     bool AddValue(IntType theValue)
0125     {
0126       const BlockType aValBit = BlockType(1) << (static_cast<IndexType>(theValue) & MASK_LOW);
0127       if ((myData & aValBit) == 0)
0128       {
0129         myData ^= aValBit;
0130         ++myMask;
0131         return true;
0132       }
0133       return false;
0134     }
0135 
0136     //! Delete integer key from this packed node.
0137     //! @return TRUE if key has been deleted
0138     bool DelValue(IntType theValue)
0139     {
0140       const BlockType aValBit = BlockType(1) << (static_cast<IndexType>(theValue) & MASK_LOW);
0141       if ((myData & aValBit) != 0)
0142       {
0143         myData ^= aValBit;
0144         myMask--;
0145         return true;
0146       }
0147       return false;
0148     }
0149 
0150     //! Return the next node having the same hash code.
0151     PackedMapNode* Next() const { return myNext; }
0152 
0153     //! Set the next node having the same hash code.
0154     void SetNext(PackedMapNode* theNext) { myNext = theNext; }
0155 
0156   public:
0157     //! Support of Map interface.
0158     size_t HashCode(size_t theUpper) const
0159     {
0160       return static_cast<size_t>(myMask >> MaskLowBits) % theUpper + 1;
0161     }
0162 
0163     //! Support of Map interface.
0164     bool IsEqual(IndexType theOther) const
0165     {
0166       return (myMask >> MaskLowBits) == (static_cast<IndexType>(theOther));
0167     }
0168 
0169   private:
0170     PackedMapNode* myNext;
0171     IndexType      myMask;
0172     BlockType      myData;
0173   };
0174 
0175 public:
0176   //! Iterator of class NCollection_PackedMap.
0177   class Iterator
0178   {
0179   public:
0180     //! Empty Constructor.
0181     Iterator()
0182         : myBuckets(nullptr),
0183           myNode(nullptr),
0184           myNbBuckets(0),
0185           myBucket(0),
0186           myIntMask(~BlockType(0)),
0187           myKey(0)
0188     {
0189     }
0190 
0191     //! Constructor.
0192     Iterator(const NCollection_PackedMap& theMap)
0193         : myBuckets(theMap.myData1),
0194           myNode(nullptr),
0195           myNbBuckets(theMap.myData1 != nullptr ? theMap.myNbBuckets : 0),
0196           myBucket(0),
0197           myIntMask(~BlockType(0))
0198     {
0199       findFirst();
0200       myKey = myNode != nullptr ? NCollection_PackedMap::findNext(myNode, myIntMask) : 0;
0201     }
0202 
0203     //! Re-initialize with the same or another Map instance.
0204     void Initialize(const NCollection_PackedMap& theMap)
0205     {
0206       myBuckets   = theMap.myData1;
0207       myBucket    = 0;
0208       myNode      = nullptr;
0209       myNbBuckets = theMap.myData1 != nullptr ? theMap.myNbBuckets : 0;
0210       findFirst();
0211 
0212       myIntMask = ~BlockType(0);
0213       myKey     = myNode != nullptr ? findNext(myNode, myIntMask) : 0;
0214     }
0215 
0216     //! Restart the iteration
0217     void Reset()
0218     {
0219       myBucket = 0;
0220       myNode   = nullptr;
0221       findFirst();
0222 
0223       myIntMask = ~BlockType(0);
0224       myKey     = myNode != nullptr ? findNext(myNode, myIntMask) : 0;
0225     }
0226 
0227     //! Query the iterated key.
0228     IntType Key() const
0229     {
0230       Standard_NoSuchObject_Raise_if((myIntMask == ~BlockType(0)),
0231                                      "NCollection_PackedMap::Iterator::Key");
0232       return myKey;
0233     }
0234 
0235     //! Return TRUE if iterator points to the node.
0236     bool More() const { return myNode != nullptr; }
0237 
0238     //! Increment the iterator
0239     void Next()
0240     {
0241       for (; myNode != nullptr; next())
0242       {
0243         myKey = NCollection_PackedMap::findNext(myNode, myIntMask);
0244         if (myIntMask != ~BlockType(0))
0245         {
0246           break;
0247         }
0248       }
0249     }
0250 
0251   private:
0252     //! Find the first non-empty bucket starting from myBucket.
0253     void findFirst()
0254     {
0255       if (myBuckets == nullptr)
0256       {
0257         return;
0258       }
0259       for (; myBucket <= myNbBuckets; ++myBucket)
0260       {
0261         myNode = myBuckets[myBucket];
0262         if (myNode != nullptr)
0263         {
0264           return;
0265         }
0266       }
0267     }
0268 
0269     //! Advance to the next node (may cross bucket boundaries).
0270     void next()
0271     {
0272       if (myBuckets == nullptr)
0273       {
0274         return;
0275       }
0276       if (myNode != nullptr)
0277       {
0278         myNode = myNode->Next();
0279         if (myNode != nullptr)
0280         {
0281           return;
0282         }
0283       }
0284       ++myBucket;
0285       while (myBucket <= myNbBuckets)
0286       {
0287         myNode = myBuckets[myBucket];
0288         if (myNode != nullptr)
0289         {
0290           return;
0291         }
0292         ++myBucket;
0293       }
0294     }
0295 
0296   private:
0297     PackedMapNode** myBuckets;
0298     PackedMapNode*  myNode;
0299     size_t          myNbBuckets;
0300     size_t          myBucket;
0301 
0302     BlockType myIntMask; //!< all bits set above the iterated position
0303     IntType   myKey;     //!< Currently iterated key
0304   };
0305 
0306 public:
0307   //! Constructor
0308   NCollection_PackedMap(const size_t theNbBuckets = 1)
0309       : myData1(nullptr),
0310         myNbBuckets(theNbBuckets),
0311         myNbPackedMapNodes(0),
0312         myExtent(0)
0313   {
0314   }
0315 
0316   //! Constructor (legacy int-taking).
0317   NCollection_PackedMap(const int theNbBuckets)
0318       : myData1(nullptr),
0319         myNbBuckets(theNbBuckets < 1 ? 1 : static_cast<size_t>(theNbBuckets)),
0320         myNbPackedMapNodes(0),
0321         myExtent(0)
0322   {
0323   }
0324 
0325   //! Copy constructor
0326   NCollection_PackedMap(const NCollection_PackedMap& theOther)
0327       : myData1(nullptr),
0328         myNbBuckets(1),
0329         myNbPackedMapNodes(0),
0330         myExtent(0)
0331   {
0332     Assign(theOther);
0333   }
0334 
0335   NCollection_PackedMap& operator=(const NCollection_PackedMap& theOther)
0336   {
0337     return Assign(theOther);
0338   }
0339 
0340   //! Move constructor
0341   NCollection_PackedMap(NCollection_PackedMap&& theOther) noexcept
0342       : myData1(theOther.myData1),
0343         myNbBuckets(theOther.myNbBuckets),
0344         myNbPackedMapNodes(theOther.myNbPackedMapNodes),
0345         myExtent(theOther.myExtent)
0346   {
0347     theOther.myData1            = nullptr;
0348     theOther.myNbBuckets        = 1;
0349     theOther.myNbPackedMapNodes = 0;
0350     theOther.myExtent           = 0;
0351   }
0352 
0353   //! Move assignment operator
0354   NCollection_PackedMap& operator=(NCollection_PackedMap&& theOther) noexcept
0355   {
0356     if (this != &theOther)
0357     {
0358       Clear();
0359       myData1                     = theOther.myData1;
0360       myNbBuckets                 = theOther.myNbBuckets;
0361       myNbPackedMapNodes          = theOther.myNbPackedMapNodes;
0362       myExtent                    = theOther.myExtent;
0363       theOther.myData1            = nullptr;
0364       theOther.myNbBuckets        = 1;
0365       theOther.myNbPackedMapNodes = 0;
0366       theOther.myExtent           = 0;
0367     }
0368     return *this;
0369   }
0370 
0371   //! Assignment operator
0372   NCollection_PackedMap& Assign(const NCollection_PackedMap& theOther)
0373   {
0374     if (this != &theOther)
0375     {
0376       Clear();
0377       if (!theOther.IsEmpty())
0378       {
0379         ReSize(theOther.myNbPackedMapNodes);
0380         const size_t nBucketsSrc = theOther.myNbBuckets;
0381         const size_t nBuckets    = myNbBuckets;
0382         for (size_t i = 0; i <= nBucketsSrc; ++i)
0383         {
0384           for (const PackedMapNode* p = theOther.myData1[i]; p != nullptr;)
0385           {
0386             const size_t aHashCode = p->HashCode(nBuckets);
0387             myData1[aHashCode]     = new PackedMapNode(p->Mask(), p->Data(), myData1[aHashCode]);
0388             ++myNbPackedMapNodes;
0389             p = p->Next();
0390           }
0391         }
0392       }
0393       myExtent = theOther.myExtent;
0394     }
0395     return *this;
0396   }
0397 
0398   //! Resize the map
0399   void ReSize(const size_t theNbBuckets)
0400   {
0401     size_t aNewBuck = NCollection_Primes::NextPrimeForMap(theNbBuckets);
0402     if (aNewBuck <= myNbBuckets)
0403     {
0404       if (!IsEmpty())
0405       {
0406         return;
0407       }
0408       aNewBuck = myNbBuckets;
0409     }
0410 
0411     PackedMapNode** aNewData = reinterpret_cast<PackedMapNode**>(
0412       Standard::AllocateOptimal((aNewBuck + 1) * sizeof(PackedMapNode*)));
0413     memset(aNewData, 0, (aNewBuck + 1) * sizeof(PackedMapNode*));
0414     if (myData1 != nullptr)
0415     {
0416       PackedMapNode** anOldData = myData1;
0417       for (size_t i = 0; i <= myNbBuckets; ++i)
0418       {
0419         for (PackedMapNode* p = anOldData[i]; p != nullptr;)
0420         {
0421           size_t         k = p->HashCode(aNewBuck);
0422           PackedMapNode* q = p->Next();
0423           p->SetNext(aNewData[k]);
0424           aNewData[k] = p;
0425           p           = q;
0426         }
0427       }
0428     }
0429 
0430     Standard::Free(myData1);
0431     myNbBuckets = aNewBuck;
0432     myData1     = aNewData;
0433   }
0434 
0435   //! Resize the map (legacy int-taking).
0436   void ReSize(const int theNbBuckets)
0437   {
0438     ReSize(static_cast<size_t>(theNbBuckets < 0 ? 0 : theNbBuckets));
0439   }
0440 
0441   //! Clear the map
0442   void Clear()
0443   {
0444     if (!IsEmpty())
0445     {
0446       for (size_t aBucketIter = 0; aBucketIter <= myNbBuckets; ++aBucketIter)
0447       {
0448         if (myData1[aBucketIter])
0449         {
0450           for (PackedMapNode* aSubNodeIter = myData1[aBucketIter]; aSubNodeIter != nullptr;)
0451           {
0452             PackedMapNode* q = aSubNodeIter->Next();
0453             delete aSubNodeIter;
0454             aSubNodeIter = q;
0455           }
0456         }
0457       }
0458     }
0459 
0460     myNbPackedMapNodes = 0;
0461     Standard::Free(myData1);
0462     myData1  = nullptr;
0463     myExtent = 0;
0464   }
0465 
0466   ~NCollection_PackedMap() { Clear(); }
0467 
0468   //! Add a key to the map
0469   //! @param[in] theKey the key to add
0470   //! @return true if the key was added, false if it already existed
0471   bool Add(const IntType theKey)
0472   {
0473     if (Resizable())
0474     {
0475       ReSize(myNbPackedMapNodes);
0476     }
0477 
0478     const IndexType aKeyInt     = packedKeyIndex(theKey);
0479     const size_t    aHashCode   = hashCode(aKeyInt, myNbBuckets);
0480     PackedMapNode*  aBucketHead = myData1[aHashCode];
0481     for (PackedMapNode* p = aBucketHead; p != nullptr; p = p->Next())
0482     {
0483       if (p->IsEqual(aKeyInt))
0484       {
0485         if (p->AddValue(theKey))
0486         {
0487           ++myExtent;
0488           return true;
0489         }
0490         return false;
0491       }
0492     }
0493 
0494     myData1[aHashCode] = new PackedMapNode(theKey, aBucketHead);
0495     ++myNbPackedMapNodes;
0496     ++myExtent;
0497     return true;
0498   }
0499 
0500   //! Check if the map contains a key
0501   //! @param[in] theKey the key to check
0502   //! @return true if the key is in the map
0503   bool Contains(const IntType theKey) const
0504   {
0505     if (IsEmpty())
0506     {
0507       return false;
0508     }
0509 
0510     const IndexType aKeyInt = packedKeyIndex(theKey);
0511     for (PackedMapNode* p = myData1[hashCode(aKeyInt, myNbBuckets)]; p != nullptr;)
0512     {
0513       if (p->IsEqual(aKeyInt))
0514       {
0515         return p->HasValue(theKey);
0516       }
0517       p = p->Next();
0518     }
0519     return false;
0520   }
0521 
0522   //! Remove a key from the map
0523   //! @param[in] theKey the key to remove
0524   //! @return true if the key was removed, false if it was not present
0525   bool Remove(const IntType theKey)
0526   {
0527     if (IsEmpty())
0528     {
0529       return false;
0530     }
0531 
0532     const IndexType aKeyInt     = packedKeyIndex(theKey);
0533     PackedMapNode*& aBucketHead = myData1[hashCode(aKeyInt, myNbBuckets)];
0534     PackedMapNode*  p           = aBucketHead;
0535     PackedMapNode*  q           = nullptr;
0536     while (p)
0537     {
0538       if (p->IsEqual(aKeyInt))
0539       {
0540         bool aResult = p->DelValue(theKey);
0541         if (aResult)
0542         {
0543           --myExtent;
0544           if (!p->HasValues())
0545           {
0546             --myNbPackedMapNodes;
0547             if (q != nullptr)
0548             {
0549               q->SetNext(p->Next());
0550             }
0551             else
0552             {
0553               aBucketHead = p->Next();
0554             }
0555             delete p;
0556           }
0557         }
0558         return aResult;
0559       }
0560       q = p;
0561       p = p->Next();
0562     }
0563     return false;
0564   }
0565 
0566   //! Returns the number of map buckets.
0567   size_t NbBuckets() const { return myNbBuckets; }
0568 
0569   //! Returns map extent (legacy int-returning API).
0570   int Extent() const { return static_cast<int>(myExtent); }
0571 
0572   //! Returns map extent (legacy int-returning API, synonym of Extent()).
0573   int Length() const { return static_cast<int>(myExtent); }
0574 
0575   //! Returns map extent.
0576   size_t Size() const { return myExtent; }
0577 
0578   //! Returns TRUE if map is empty.
0579   bool IsEmpty() const { return myNbPackedMapNodes == 0; }
0580 
0581   //! Query the minimal contained key value.
0582   IntType GetMinimalMapped() const
0583   {
0584     if (IsEmpty())
0585     {
0586       return std::numeric_limits<IntType>::max();
0587     }
0588 
0589     IntType              aResult    = std::numeric_limits<IntType>::max();
0590     const PackedMapNode* pFoundNode = nullptr;
0591     for (size_t i = 0; i <= myNbBuckets; ++i)
0592     {
0593       for (const PackedMapNode* p = myData1[i]; p != nullptr; p = p->Next())
0594       {
0595         const IntType aKey = p->Key();
0596         if (aResult > aKey)
0597         {
0598           aResult    = aKey;
0599           pFoundNode = p;
0600         }
0601       }
0602     }
0603     if (pFoundNode)
0604     {
0605       BlockType aFullMask = ~BlockType(0);
0606       aResult             = findNext(pFoundNode, aFullMask);
0607     }
0608     return aResult;
0609   }
0610 
0611   //! Query the maximal contained key value.
0612   IntType GetMaximalMapped() const
0613   {
0614     if (IsEmpty())
0615     {
0616       return std::numeric_limits<IntType>::lowest();
0617     }
0618 
0619     IntType              aResult    = std::numeric_limits<IntType>::lowest();
0620     const PackedMapNode* pFoundNode = nullptr;
0621     for (size_t i = 0; i <= myNbBuckets; ++i)
0622     {
0623       for (const PackedMapNode* p = myData1[i]; p != nullptr; p = p->Next())
0624       {
0625         const IntType aKey = p->Key();
0626         if (aResult < aKey)
0627         {
0628           aResult    = aKey;
0629           pFoundNode = p;
0630         }
0631       }
0632     }
0633     if (pFoundNode)
0634     {
0635       BlockType aFullMask = ~BlockType(0);
0636       aResult             = findPrev(pFoundNode, aFullMask);
0637     }
0638     return aResult;
0639   }
0640 
0641 public:
0642   //! @name Deprecated boolean operations (use NCollection_PackedMapAlgo instead)
0643 
0644   //! @deprecated Use NCollection_PackedMapAlgo::Union() instead
0645   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0646                       "NCollection_PackedMapAlgo.hxx instead.")
0647   void Union(const NCollection_PackedMap& theLeft, const NCollection_PackedMap& theRight);
0648 
0649   //! @deprecated Use NCollection_PackedMapAlgo::Unite() instead
0650   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0651                       "NCollection_PackedMapAlgo.hxx instead.")
0652   bool Unite(const NCollection_PackedMap& theOther);
0653 
0654   //! @deprecated Use NCollection_PackedMapAlgo::Intersection() instead
0655   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0656                       "NCollection_PackedMapAlgo.hxx instead.")
0657   void Intersection(const NCollection_PackedMap& theLeft, const NCollection_PackedMap& theRight);
0658 
0659   //! @deprecated Use NCollection_PackedMapAlgo::Intersect() instead
0660   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0661                       "NCollection_PackedMapAlgo.hxx instead.")
0662   bool Intersect(const NCollection_PackedMap& theOther);
0663 
0664   //! @deprecated Use NCollection_PackedMapAlgo::Subtraction() instead
0665   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0666                       "NCollection_PackedMapAlgo.hxx instead.")
0667   void Subtraction(const NCollection_PackedMap& theLeft, const NCollection_PackedMap& theRight);
0668 
0669   //! @deprecated Use NCollection_PackedMapAlgo::Subtract() instead
0670   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0671                       "NCollection_PackedMapAlgo.hxx instead.")
0672   bool Subtract(const NCollection_PackedMap& theOther);
0673 
0674   //! @deprecated Use NCollection_PackedMapAlgo::Difference() instead
0675   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0676                       "NCollection_PackedMapAlgo.hxx instead.")
0677   void Difference(const NCollection_PackedMap& theLeft, const NCollection_PackedMap& theRight);
0678 
0679   //! @deprecated Use NCollection_PackedMapAlgo::Differ() instead
0680   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0681                       "NCollection_PackedMapAlgo.hxx instead.")
0682   bool Differ(const NCollection_PackedMap& theOther);
0683 
0684   //! @deprecated Use NCollection_PackedMapAlgo::IsEqual() instead
0685   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0686                       "NCollection_PackedMapAlgo.hxx instead.")
0687   bool IsEqual(const NCollection_PackedMap& theOther) const;
0688 
0689   //! @deprecated Use NCollection_PackedMapAlgo::IsSubset() instead
0690   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0691                       "NCollection_PackedMapAlgo.hxx instead.")
0692   bool IsSubset(const NCollection_PackedMap& theOther) const;
0693 
0694   //! @deprecated Use NCollection_PackedMapAlgo::HasIntersection() instead
0695   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0696                       "NCollection_PackedMapAlgo.hxx instead.")
0697   bool HasIntersection(const NCollection_PackedMap& theOther) const;
0698 
0699   //! @deprecated Use NCollection_PackedMapAlgo::Contains() instead
0700   Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from "
0701                       "NCollection_PackedMapAlgo.hxx instead.")
0702   bool Contains(const NCollection_PackedMap& theOther) const;
0703 
0704 protected:
0705   //! Returns TRUE if resizing the map should be considered.
0706   bool Resizable() const { return IsEmpty() || (myNbPackedMapNodes > myNbBuckets); }
0707 
0708   //! Return an integer index for specified key.
0709   static IndexType packedKeyIndex(IntType theKey)
0710   {
0711     return static_cast<IndexType>(theKey) >> MaskLowBits;
0712   }
0713 
0714   //! Compute hash code for a key index.
0715   static size_t hashCode(IndexType theKeyIndex, size_t theNbBuckets)
0716   {
0717     return static_cast<size_t>(theKeyIndex) % theNbBuckets + 1;
0718   }
0719 
0720   //! Compute the population (i.e., the number of non-zero bits) of the block.
0721   //! The population is stored decremented as it is defined in PackedMapNode.
0722   static size_t population(IndexType& theMask, BlockType theData)
0723   {
0724     if constexpr (Is64Bit)
0725     {
0726       // 64-bit population count
0727       uint64_t aRes = theData - ((theData >> 1) & 0x5555555555555555ULL);
0728       aRes          = (aRes & 0x3333333333333333ULL) + ((aRes >> 2) & 0x3333333333333333ULL);
0729       aRes          = (aRes + (aRes >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
0730       aRes          = aRes + (aRes >> 8);
0731       aRes          = aRes + (aRes >> 16);
0732       aRes          = aRes + (aRes >> 32);
0733       theMask       = (theMask & MASK_HIGH) | ((static_cast<IndexType>(aRes) - 1) & MASK_LOW);
0734       return size_t(aRes & 0x7f);
0735     }
0736     else
0737     {
0738       // 32-bit population count
0739       uint32_t aRes =
0740         static_cast<uint32_t>(theData) - ((static_cast<uint32_t>(theData) >> 1) & 0x55555555);
0741       aRes    = (aRes & 0x33333333) + ((aRes >> 2) & 0x33333333);
0742       aRes    = (aRes + (aRes >> 4)) & 0x0f0f0f0f;
0743       aRes    = aRes + (aRes >> 8);
0744       aRes    = aRes + (aRes >> 16);
0745       theMask = (theMask & MASK_HIGH) | ((aRes - 1) & MASK_LOW);
0746       return size_t(aRes & 0x3f);
0747     }
0748   }
0749 
0750   //! Find the smallest non-zero bit under the given mask.
0751   //! Outputs the new mask that does not contain the detected bit.
0752   static IntType findNext(const PackedMapNode* theNode, BlockType& theMask)
0753   {
0754     BlockType val    = theNode->Data() & theMask;
0755     int       nZeros = 0;
0756     if (val == 0)
0757     {
0758       theMask = ~BlockType(0); // void, nothing to do
0759     }
0760     else
0761     {
0762       BlockType aMask = ~BlockType(0);
0763       if constexpr (Is64Bit)
0764       {
0765         if ((val & 0x00000000ffffffffULL) == 0)
0766         {
0767           aMask  = 0xffffffff00000000ULL;
0768           nZeros = 32;
0769           val >>= 32;
0770         }
0771       }
0772       if ((val & 0x0000ffff) == 0)
0773       {
0774         aMask <<= 16;
0775         nZeros += 16;
0776         val >>= 16;
0777       }
0778       if ((val & 0x000000ff) == 0)
0779       {
0780         aMask <<= 8;
0781         nZeros += 8;
0782         val >>= 8;
0783       }
0784       if ((val & 0x0000000f) == 0)
0785       {
0786         aMask <<= 4;
0787         nZeros += 4;
0788         val >>= 4;
0789       }
0790       if ((val & 0x00000003) == 0)
0791       {
0792         aMask <<= 2;
0793         nZeros += 2;
0794         val >>= 2;
0795       }
0796       if ((val & 0x00000001) == 0)
0797       {
0798         aMask <<= 1;
0799         nZeros++;
0800       }
0801       theMask = (aMask << 1);
0802     }
0803     return static_cast<IntType>(nZeros) + theNode->Key();
0804   }
0805 
0806   //! Find the highest non-zero bit under the given mask.
0807   //! Outputs the new mask that does not contain the detected bit.
0808   static IntType findPrev(const PackedMapNode* theNode, BlockType& theMask)
0809   {
0810     BlockType val    = theNode->Data() & theMask;
0811     int       nZeros = 0;
0812     if (val == 0)
0813     {
0814       theMask = ~BlockType(0); // void, nothing to do
0815     }
0816     else
0817     {
0818       BlockType aMask = ~BlockType(0);
0819       if constexpr (Is64Bit)
0820       {
0821         if ((val & 0xffffffff00000000ULL) == 0)
0822         {
0823           aMask  = 0x00000000ffffffffULL;
0824           nZeros = 32;
0825           val <<= 32;
0826         }
0827       }
0828       if ((val & BlockType(0xffff0000) << (Is64Bit ? 32 : 0)) == 0)
0829       {
0830         aMask >>= 16;
0831         nZeros += 16;
0832         val <<= 16;
0833       }
0834       if ((val & BlockType(0xff000000) << (Is64Bit ? 32 : 0)) == 0)
0835       {
0836         aMask >>= 8;
0837         nZeros += 8;
0838         val <<= 8;
0839       }
0840       if ((val & BlockType(0xf0000000) << (Is64Bit ? 32 : 0)) == 0)
0841       {
0842         aMask >>= 4;
0843         nZeros += 4;
0844         val <<= 4;
0845       }
0846       if ((val & BlockType(0xc0000000) << (Is64Bit ? 32 : 0)) == 0)
0847       {
0848         aMask >>= 2;
0849         nZeros += 2;
0850         val <<= 2;
0851       }
0852       if ((val & BlockType(0x80000000) << (Is64Bit ? 32 : 0)) == 0)
0853       {
0854         aMask >>= 1;
0855         nZeros++;
0856       }
0857       theMask = (aMask >> 1);
0858     }
0859     return static_cast<IntType>((BitsPerBlock - 1) - nZeros) + theNode->Key();
0860   }
0861 
0862 private:
0863   PackedMapNode** myData1;            //!< data array
0864   size_t          myNbBuckets;        //!< number of buckets (size of data array)
0865   size_t          myNbPackedMapNodes; //!< amount of packed map nodes
0866   size_t          myExtent;           //!< extent of this map (number of unpacked integer keys)
0867 };
0868 
0869 // Include algorithm header after class definition to avoid circular dependency
0870 #include <NCollection_PackedMapAlgo.hxx>
0871 
0872 // Implementation of deprecated methods
0873 template <typename IntType>
0874 void NCollection_PackedMap<IntType>::Union(const NCollection_PackedMap& theLeft,
0875                                            const NCollection_PackedMap& theRight)
0876 {
0877   NCollection_PackedMapAlgo::Union(*this, theLeft, theRight);
0878 }
0879 
0880 template <typename IntType>
0881 bool NCollection_PackedMap<IntType>::Unite(const NCollection_PackedMap& theOther)
0882 {
0883   return NCollection_PackedMapAlgo::Unite(*this, theOther);
0884 }
0885 
0886 template <typename IntType>
0887 void NCollection_PackedMap<IntType>::Intersection(const NCollection_PackedMap& theLeft,
0888                                                   const NCollection_PackedMap& theRight)
0889 {
0890   NCollection_PackedMapAlgo::Intersection(*this, theLeft, theRight);
0891 }
0892 
0893 template <typename IntType>
0894 bool NCollection_PackedMap<IntType>::Intersect(const NCollection_PackedMap& theOther)
0895 {
0896   return NCollection_PackedMapAlgo::Intersect(*this, theOther);
0897 }
0898 
0899 template <typename IntType>
0900 void NCollection_PackedMap<IntType>::Subtraction(const NCollection_PackedMap& theLeft,
0901                                                  const NCollection_PackedMap& theRight)
0902 {
0903   NCollection_PackedMapAlgo::Subtraction(*this, theLeft, theRight);
0904 }
0905 
0906 template <typename IntType>
0907 bool NCollection_PackedMap<IntType>::Subtract(const NCollection_PackedMap& theOther)
0908 {
0909   return NCollection_PackedMapAlgo::Subtract(*this, theOther);
0910 }
0911 
0912 template <typename IntType>
0913 void NCollection_PackedMap<IntType>::Difference(const NCollection_PackedMap& theLeft,
0914                                                 const NCollection_PackedMap& theRight)
0915 {
0916   NCollection_PackedMapAlgo::Difference(*this, theLeft, theRight);
0917 }
0918 
0919 template <typename IntType>
0920 bool NCollection_PackedMap<IntType>::Differ(const NCollection_PackedMap& theOther)
0921 {
0922   return NCollection_PackedMapAlgo::Differ(*this, theOther);
0923 }
0924 
0925 template <typename IntType>
0926 bool NCollection_PackedMap<IntType>::IsEqual(const NCollection_PackedMap& theOther) const
0927 {
0928   return NCollection_PackedMapAlgo::IsEqual(*this, theOther);
0929 }
0930 
0931 template <typename IntType>
0932 bool NCollection_PackedMap<IntType>::IsSubset(const NCollection_PackedMap& theOther) const
0933 {
0934   return NCollection_PackedMapAlgo::IsSubset(*this, theOther);
0935 }
0936 
0937 template <typename IntType>
0938 bool NCollection_PackedMap<IntType>::HasIntersection(const NCollection_PackedMap& theOther) const
0939 {
0940   return NCollection_PackedMapAlgo::HasIntersection(*this, theOther);
0941 }
0942 
0943 template <typename IntType>
0944 bool NCollection_PackedMap<IntType>::Contains(const NCollection_PackedMap& theOther) const
0945 {
0946   return NCollection_PackedMapAlgo::Contains(*this, theOther);
0947 }
0948 
0949 #endif // NCollection_PackedMap_HeaderFile