Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:49:05

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