Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 08:42:14

0001 // Created on: 2005-11-05
0002 // Created by: Alexander GRIGORIEV
0003 // Copyright (c) 2005-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef TColStd_PackedMapOfInteger_HeaderFile
0017 #define TColStd_PackedMapOfInteger_HeaderFile
0018 
0019 #include <Standard.hxx>
0020 #include <Standard_Boolean.hxx>
0021 #include <Standard_DefineAlloc.hxx>
0022 #include <Standard_Integer.hxx>
0023 #include <Standard_NoSuchObject.hxx>
0024 #include <Standard_OStream.hxx>
0025 #include <Standard_Handle.hxx>
0026 
0027 /**
0028  * Optimized Map of integer values. Each block of 32 integers is stored in 8 bytes in memory.
0029  */
0030 class TColStd_PackedMapOfInteger
0031 {
0032 public:
0033   DEFINE_STANDARD_ALLOC
0034 
0035 private:
0036 
0037   //! 5 lower bits
0038   static const unsigned int MASK_LOW = 0x001f;
0039 
0040   //! 27 upper bits
0041   static const unsigned int MASK_HIGH = ~MASK_LOW;
0042 
0043   //! Class implementing a block of 32 consecutive integer values as a node of a Map collection.
0044   //! The data are stored in 64 bits as:
0045   //!  - bits  0 - 4 : (number of integers stored in the block) - 1;
0046   //!  - bits  5 - 31: base address of the block of integers (low bits assumed 0)
0047   //!  - bits 32 - 63: 32-bit field where each bit indicates the presence of the corresponding integer in the block.
0048   //!                  Number of non-zero bits must be equal to the number expressed in bits 0-4.
0049   class TColStd_intMapNode
0050   {
0051   public:
0052     TColStd_intMapNode (TColStd_intMapNode* thePtr = NULL)
0053     : myNext (thePtr), myMask (0), myData (0) {}
0054 
0055     TColStd_intMapNode (Standard_Integer theValue, TColStd_intMapNode*& thePtr)
0056     : myNext (thePtr),
0057       myMask ((unsigned int) (theValue & MASK_HIGH)),
0058       myData (1 << (theValue & MASK_LOW)) {}
0059 
0060     TColStd_intMapNode (unsigned int theMask, unsigned int theData, TColStd_intMapNode* thePtr)
0061     : myNext (thePtr),
0062       myMask (theMask),
0063       myData (theData) {}
0064 
0065     unsigned int Mask() const { return myMask; }
0066 
0067     unsigned int Data() const { return myData; }
0068 
0069     unsigned int& ChangeMask() { return myMask; }
0070 
0071     unsigned int& ChangeData() { return myData; }
0072 
0073     //! Compute the sequential index of this packed node in the map.
0074     Standard_Integer Key() const { return Standard_Integer (myMask & MASK_HIGH); }
0075 
0076     //! Return the number of set integer keys.
0077     size_t NbValues() const { return size_t(myMask & MASK_LOW) + 1; }
0078 
0079     //! Return TRUE if this packed node is not empty.
0080     Standard_Boolean HasValues() const { return (myData != 0); }
0081 
0082     //! Return TRUE if the given integer key is set within this packed node.
0083     Standard_Integer HasValue (Standard_Integer theValue) const { return (myData & (1 << (theValue & MASK_LOW))); }
0084 
0085     //! Add integer key to this packed node.
0086     //! @return TRUE if key has been added
0087     Standard_Boolean AddValue (Standard_Integer theValue)
0088     {
0089       const Standard_Integer aValInt = (1 << (theValue & MASK_LOW));
0090       if ((myData & aValInt) == 0)
0091       {
0092         myData ^= aValInt;
0093         ++myMask;
0094         return Standard_True;
0095       }
0096       return Standard_False;
0097     }
0098 
0099     //! Delete integer key from this packed node.
0100     //! @return TRUE if key has been deleted
0101     Standard_Boolean DelValue (Standard_Integer theValue)
0102     {
0103       const Standard_Integer aValInt = (1 << (theValue & MASK_LOW));
0104       if ((myData & aValInt) != 0)
0105       {
0106         myData ^= aValInt;
0107         myMask--;
0108         return Standard_True;
0109       }
0110       return Standard_False;
0111     }
0112 
0113     //! Find the smallest non-zero bit under the given mask. Outputs the new mask
0114     //! that does not contain the detected bit.
0115     Standard_Integer FindNext (unsigned int& theMask) const;
0116 
0117     //! Return the next node having the same hash code.
0118     TColStd_intMapNode* Next() const { return myNext; }
0119 
0120     //! Set the next node having the same hash code.
0121     void SetNext (TColStd_intMapNode* theNext) { myNext = theNext; }
0122 
0123   public:
0124     //! Support of Map interface.
0125     Standard_Integer HashCode (Standard_Integer theUpper) const
0126     {
0127       return (myMask >> 5) % theUpper + 1;
0128     }
0129 
0130     //! Support of Map interface.
0131     Standard_Boolean IsEqual (Standard_Integer theOther) const
0132     {
0133       return ((myMask >> 5) == (unsigned)theOther);
0134     }
0135 
0136   private:
0137     TColStd_intMapNode* myNext;
0138     unsigned int myMask;
0139     unsigned int myData;
0140   };
0141 
0142 public:
0143 
0144   //! Iterator of class TColStd_PackedMapOfInteger.
0145   class Iterator
0146   {
0147   public:
0148 
0149     /// Empty Constructor.
0150     Iterator()
0151     : myBuckets (NULL),
0152       myNode (NULL),
0153       myNbBuckets (-1),
0154       myBucket (-1),
0155       myIntMask (~0U),
0156       myKey (0) {}
0157 
0158     /// Constructor.
0159     Iterator (const TColStd_PackedMapOfInteger& theMap)
0160     : myBuckets (theMap.myData1),
0161       myNode (NULL),
0162       myNbBuckets (theMap.myData1 != NULL ? theMap.myNbBuckets : -1),
0163       myBucket (-1),
0164       myIntMask (~0U)
0165     {
0166       next();
0167       myKey = myNode != NULL ? TColStd_intMapNode_findNext (myNode, myIntMask) : 0;
0168     }
0169 
0170     //! Re-initialize with the same or another Map instance.
0171     void Initialize (const TColStd_PackedMapOfInteger& theMap)
0172     {
0173       myBuckets = theMap.myData1;
0174       myBucket = -1;
0175       myNode = NULL;
0176       myNbBuckets = theMap.myData1 != NULL ? theMap.myNbBuckets : -1;
0177       next();
0178 
0179       myIntMask = ~0U;
0180       myKey = myNode != NULL ? TColStd_intMapNode_findNext (myNode, myIntMask) : 0;
0181     }
0182 
0183     //! Restart the iteration
0184     void Reset()
0185     {
0186       myBucket = -1;
0187       myNode = NULL;
0188       next();
0189 
0190       myIntMask = ~0U;
0191       myKey = myNode != NULL ? TColStd_intMapNode_findNext (myNode, myIntMask) : 0;
0192     }
0193 
0194     //! Query the iterated key.
0195     Standard_Integer Key() const
0196     {
0197       Standard_NoSuchObject_Raise_if ((myIntMask == ~0U), "TColStd_MapIteratorOfPackedMapOfInteger::Key");
0198       return myKey;
0199     }
0200 
0201     //! Return TRUE if iterator points to the node.
0202     Standard_Boolean More() const { return myNode != NULL; }
0203 
0204     //! Increment the iterator
0205     void Next()
0206     {
0207       for (; myNode != NULL; next())
0208       {
0209         myKey = TColStd_intMapNode_findNext (myNode, myIntMask);
0210         if (myIntMask != ~0u)
0211         {
0212           break;
0213         }
0214       }
0215     }
0216   private:
0217     //! Go to the next bucket in the map.
0218     void next()
0219     {
0220       if (myBuckets == NULL)
0221       {
0222         return;
0223       }
0224 
0225       if (myNode != NULL)
0226       {
0227         myNode = myNode->Next();
0228       }
0229 
0230       while (myNode == NULL)
0231       {
0232         ++myBucket;
0233         if (myBucket > myNbBuckets)
0234         {
0235           return;
0236         }
0237         myNode = myBuckets[myBucket];
0238       }
0239     }
0240 
0241   private:
0242     TColStd_intMapNode** myBuckets;
0243     TColStd_intMapNode*  myNode;
0244     Standard_Integer myNbBuckets;
0245     Standard_Integer myBucket;
0246 
0247     unsigned int     myIntMask; //!< all bits set above the iterated position
0248     Standard_Integer myKey;     //!< Currently iterated key
0249   };
0250 
0251 public:
0252 
0253   //! Constructor
0254   TColStd_PackedMapOfInteger (const Standard_Integer theNbBuckets = 1)
0255   : myData1 (NULL),
0256     myNbBuckets (theNbBuckets),
0257     myNbPackedMapNodes (0),
0258     myExtent (0) {}
0259 
0260   //! Copy constructor
0261   TColStd_PackedMapOfInteger (const TColStd_PackedMapOfInteger& theOther)
0262   : myData1 (NULL),
0263     myNbBuckets (1),
0264     myNbPackedMapNodes (0),
0265     myExtent (0)
0266   {
0267     Assign (theOther);
0268   }
0269 
0270   inline TColStd_PackedMapOfInteger&
0271                           operator =  (const TColStd_PackedMapOfInteger& Other) 
0272   { return Assign(Other); }
0273 
0274   Standard_EXPORT TColStd_PackedMapOfInteger&
0275                           Assign        (const TColStd_PackedMapOfInteger&);
0276   Standard_EXPORT  void   ReSize        (const Standard_Integer NbBuckets);
0277   Standard_EXPORT  void   Clear         ();
0278   ~TColStd_PackedMapOfInteger() { Clear(); }
0279   Standard_EXPORT  Standard_Boolean
0280                           Add           (const Standard_Integer aKey);
0281   Standard_EXPORT  Standard_Boolean
0282                           Contains      (const Standard_Integer aKey) const;
0283   Standard_EXPORT  Standard_Boolean
0284                           Remove        (const Standard_Integer aKey);
0285 
0286   //! Returns the number of map buckets (not that since integers are packed in this map, the number is smaller than extent).
0287   Standard_Integer NbBuckets() const { return myNbBuckets; }
0288 
0289   //! Returns map extent.
0290   Standard_Integer Extent() const { return Standard_Integer (myExtent); }
0291 
0292   //! Returns TRUE if map is empty.
0293   Standard_Boolean IsEmpty() const { return myNbPackedMapNodes == 0; }
0294 
0295   /**
0296    * Query the minimal contained key value.
0297    */
0298   Standard_EXPORT Standard_Integer GetMinimalMapped () const;
0299 
0300   /**
0301    * Query the maximal contained key value.
0302    */
0303   Standard_EXPORT Standard_Integer GetMaximalMapped () const;
0304 
0305   //! Prints useful statistics about the map.
0306   //! It can be used to test the quality of the hashcoding.
0307   Standard_EXPORT void Statistics (Standard_OStream& theStream) const;
0308 
0309 public:
0310   //!@name Boolean operations with maps as sets of integers
0311   //!@{
0312 
0313   /**
0314    * Sets this Map to be the result of union (aka addition, fuse, merge, boolean OR) operation between two given Maps.
0315    * The new Map contains the values that are contained either in the first map or in the second map or in both.
0316    * All previous contents of this Map is cleared. This map (result of the boolean operation) can also be passed as one of operands.
0317    */
0318   Standard_EXPORT void Union (const TColStd_PackedMapOfInteger&,
0319                               const TColStd_PackedMapOfInteger&);
0320 
0321   /**
0322    * Apply to this Map the boolean operation union (aka addition, fuse, merge, boolean OR) with another (given) Map.
0323    * The result contains the values that were previously contained in this map or contained in the given (operand) map.
0324    * This algorithm is similar to method Union().
0325    * @return True if content of this map is changed
0326    */
0327   Standard_EXPORT Standard_Boolean Unite (const TColStd_PackedMapOfInteger&);
0328 
0329   /**
0330    * Overloaded operator version of Unite().
0331    */
0332   TColStd_PackedMapOfInteger& operator |= (const TColStd_PackedMapOfInteger& MM)
0333   { Unite(MM); return *this; }
0334 
0335   /**
0336    * Sets this Map to be the result of intersection (aka multiplication, common, boolean AND) operation between two given Maps.
0337    * The new Map contains only the values that are contained in both map operands.
0338    * All previous contents of this Map is cleared. This same map (result of the boolean operation) can also be used as one of operands.
0339    * The order of operands makes no difference; the method minimizes internally the number of iterations using the smallest map for the loop.
0340    */
0341   Standard_EXPORT void Intersection (const TColStd_PackedMapOfInteger&,
0342                                      const TColStd_PackedMapOfInteger&);
0343 
0344   /**
0345    * Apply to this Map the intersection operation (aka multiplication, common,  boolean AND) with another (given) Map.
0346    * The result contains only the values that are contained in both this and the given maps.
0347    * This algorithm is similar to method Intersection().
0348    * @return True if content of this map is changed
0349    */
0350   Standard_EXPORT Standard_Boolean Intersect (const TColStd_PackedMapOfInteger&);
0351 
0352   /**
0353    * Overloaded operator version of Intersect().
0354    */
0355   TColStd_PackedMapOfInteger& operator &= (const TColStd_PackedMapOfInteger& MM)
0356   { Intersect(MM); return *this; }
0357 
0358   /**
0359    * Sets this Map to be the result of subtraction
0360    * (aka set-theoretic difference, relative complement, exclude, cut, boolean NOT) operation between two given Maps.
0361    * The new Map contains only the values that are contained in the first map operands and not contained in the second one.
0362    * All previous contents of this Map is cleared.
0363    * This map (result of the boolean operation) can also be used as the first operand.
0364    */
0365   Standard_EXPORT void Subtraction (const TColStd_PackedMapOfInteger&,
0366                                     const TColStd_PackedMapOfInteger&);
0367 
0368   /**
0369    * Apply to this Map the subtraction (aka set-theoretic difference, relative complement, exclude, cut, boolean NOT) operation with another (given) Map.
0370    * The result contains only the values that were previously contained in this map and not contained in this map.
0371    * This algorithm is similar to method Subtract() with two operands.
0372    * @return True if contents of this map is changed
0373    */
0374   Standard_EXPORT Standard_Boolean Subtract (const TColStd_PackedMapOfInteger&);
0375 
0376   /**
0377    * Overloaded operator version of Subtract().
0378    */
0379   TColStd_PackedMapOfInteger& operator -= (const TColStd_PackedMapOfInteger& MM)
0380   { Subtract(MM); return *this; }
0381 
0382   /**
0383    * Sets this Map to be the result of symmetric difference (aka exclusive disjunction, boolean XOR) operation between two given Maps.
0384    * The new Map contains the values that are contained only in the first or the second operand maps but not in both.
0385    * All previous contents of this Map is cleared.
0386    * This map (result of the boolean operation) can also be used as one of operands.
0387    */
0388   Standard_EXPORT void Difference (const TColStd_PackedMapOfInteger&,
0389                                    const TColStd_PackedMapOfInteger&);
0390 
0391   /**
0392    * Apply to this Map the symmetric difference (aka exclusive disjunction, boolean XOR) operation with another (given) Map.
0393    * The result contains the values that are contained only in this or the operand map, but not in both.
0394    * This algorithm is similar to method Difference().
0395    * @return True if contents of this map is changed
0396    */
0397   Standard_EXPORT Standard_Boolean Differ (const TColStd_PackedMapOfInteger&);
0398 
0399   /**
0400    * Overloaded operator version of Differ().
0401    */
0402   TColStd_PackedMapOfInteger& operator ^= (const TColStd_PackedMapOfInteger& MM)
0403   { Differ(MM); return *this; }
0404 
0405   /**
0406    * Returns True if this map is equal to the given one, i.e. they contain the
0407    * same sets of elements
0408    */
0409   Standard_EXPORT Standard_Boolean IsEqual (const TColStd_PackedMapOfInteger&) const;
0410 
0411   /**
0412    * Overloaded operator version of IsEqual().
0413    */
0414   Standard_Boolean operator == (const TColStd_PackedMapOfInteger& MM) const
0415   { return IsEqual(MM); }
0416 
0417   /**
0418    * Returns True if this map is subset of the given one, i.e. all elements 
0419    * contained in this map is contained also in the operand map.
0420    * if this map is empty that this method returns true for any operand map.
0421    */
0422   Standard_EXPORT Standard_Boolean IsSubset (const TColStd_PackedMapOfInteger&) const;
0423 
0424   /**
0425    * Overloaded operator version of IsSubset().
0426    */
0427   Standard_Boolean operator <= (const TColStd_PackedMapOfInteger& MM) const
0428   { return IsSubset(MM); }
0429 
0430   /**
0431    * Returns True if this map has common items with the given one.
0432    */
0433   Standard_EXPORT Standard_Boolean HasIntersection (const TColStd_PackedMapOfInteger&) const;
0434 
0435   //!@}
0436   
0437  protected:
0438 
0439    //! Returns TRUE if resizing the map should be considered.
0440    Standard_Boolean Resizable() const { return IsEmpty() || (myNbPackedMapNodes > myNbBuckets); }
0441 
0442    //! Return an integer index for specified key.
0443    static Standard_Integer packedKeyIndex (Standard_Integer theKey) { return (unsigned)theKey >> 5; }
0444 
0445 private:
0446 
0447   //! Find the smallest non-zero bit under the given mask.
0448   //! Outputs the new mask that does not contain the detected bit.
0449   Standard_EXPORT static Standard_Integer TColStd_intMapNode_findNext (const TColStd_intMapNode* theNode,
0450                                                                        unsigned int& theMask);
0451 
0452   //! Find the highest non-zero bit under the given mask.
0453   //! Outputs the new mask that does not contain the detected bit.
0454   Standard_EXPORT static Standard_Integer TColStd_intMapNode_findPrev (const TColStd_intMapNode* theNode,
0455                                                                        unsigned int& theMask);
0456 
0457   //! Compute the population (i.e., the number of non-zero bits) of the 32-bit word theData.
0458   //! The population is stored decremented as it is defined in TColStd_intMapNode.
0459   //! Source: H.S.Warren, Hacker's Delight, Addison-Wesley Inc. 2002, Ch.5.1
0460   static size_t TColStd_Population (unsigned int& theMask, unsigned int theData)
0461   {
0462     unsigned int aRes = theData - ((theData>>1) & 0x55555555);
0463     aRes  = (aRes & 0x33333333) + ((aRes>>2)    & 0x33333333);
0464     aRes  = (aRes + (aRes>>4)) & 0x0f0f0f0f;
0465     aRes  = aRes + (aRes>>8);
0466     aRes  = aRes + (aRes>>16);
0467     theMask = (theMask & TColStd_PackedMapOfInteger::MASK_HIGH) | ((aRes - 1) & TColStd_PackedMapOfInteger::MASK_LOW);
0468     return size_t(aRes & 0x3f);
0469   }
0470 
0471 private:
0472 
0473   TColStd_intMapNode** myData1;            //!< data array
0474   Standard_Integer     myNbBuckets;        //!< number of buckets (size of data array)
0475   Standard_Integer     myNbPackedMapNodes; //!< amount of packed map nodes
0476   Standard_Size        myExtent;           //!< extent of this map (number of unpacked integer keys)
0477 };
0478 
0479 #endif