Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:04:20

0001 // Created on: 2002-10-18
0002 // Created by: Michael SAZONOV
0003 // Copyright (c) 2002-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 NCollection_UBTreeFiller_HeaderFile
0017 #define NCollection_UBTreeFiller_HeaderFile
0018 
0019 #include <NCollection_UBTree.hxx>
0020 #include <NCollection_Vector.hxx>
0021 
0022 #include <random>
0023 
0024 /**
0025  * This class is used to fill an UBTree in a random order.
0026  * The quality of a tree is much better (from the point of view of
0027  * the search time) if objects are added to it in a random order to
0028  * avoid adding a chain of neerby objects one following each other.
0029  *
0030  * This class collects objects to be added, and then add them to the tree
0031  * in a random order.
0032  */
0033 template <class TheObjType, class TheBndType> class NCollection_UBTreeFiller
0034 {
0035  public:
0036   // ---------- PUBLIC TYPES ----------
0037 
0038   //! Structure of pair (object, bnd box)
0039   struct ObjBnd
0040   {
0041     TheObjType  myObj;
0042     TheBndType  myBnd;
0043     ObjBnd (const TheObjType& theObj, const TheBndType& theBnd)
0044       : myObj(theObj), myBnd(theBnd) {}
0045     ObjBnd ()
0046       : myObj(TheObjType()), myBnd(TheBndType()) {}
0047   };
0048 
0049   //! UBTree algorithm
0050   typedef NCollection_UBTree<TheObjType, TheBndType>    UBTree;
0051   typedef typename UBTree::TreeNode                     UBTreeNode;
0052 
0053 
0054   // ---------- PUBLIC METHODS ----------
0055 
0056   /**
0057    * Constructor.
0058    * @param theTree
0059    *   Tree instance that is to be filled.
0060    * @param theAlloc
0061    *   Allocator for the Filler data.
0062    * @param isFullRandom
0063    *   Takes effect when the number of items is large (order of 50,000). When
0064    *   it is True, the code uses the maximal randomization allowing a better
0065    *   balanced tree. If False, the randomization/tree balance are worse but
0066    *   the tree filling is faster due to better utilisation of CPU L1/L2 cache.
0067    */ 
0068   NCollection_UBTreeFiller (UBTree& theTree,
0069                             const Handle(NCollection_BaseAllocator)& theAlloc=0L,
0070                             const Standard_Boolean isFullRandom = Standard_True)
0071     : myTree(theTree), mySeqPtr(256, theAlloc),
0072       myRandGen (5489u /* == std::mt19937::default_seed, not defined in older environments, e.g, on Debian 6.0 with GCC 4.4.5 */),
0073       myIsFullRandom (isFullRandom) {}
0074 
0075   //! Adds a pair (theObj, theBnd) to my sequence
0076   void Add (const TheObjType& theObj, const TheBndType& theBnd)
0077   { mySeqPtr.Append (ObjBnd (theObj, theBnd)); }
0078 
0079   /**
0080    * Fills the tree with the objects from my sequence. This method clears
0081    * the internal buffer of added items making sure that no item would be added
0082    * twice.
0083    * @return
0084    *   the number of objects added to the tree.
0085    */
0086   Standard_Integer Fill ();
0087 
0088   /**
0089    * Remove all data from Filler, partculary if the Tree no more needed
0090    * so the destructor of this Filler should not populate the useless Tree.
0091    */
0092   void                             Reset()      { mySeqPtr.Clear(); }
0093 
0094   /**
0095    * Check the filled tree for the total number of items and the balance
0096    * outputting these results to std::ostream.
0097    * @return
0098    *   the tree size (the same value is returned by method Fill()).
0099    */ 
0100   Standard_Integer CheckTree (Standard_OStream& theStream);
0101 
0102   /**
0103    * Destructor. Fills the tree with accumulated items if they have not been
0104    * passed by a previous call of method Fill().
0105    */
0106   ~NCollection_UBTreeFiller ()
0107   {
0108     if (mySeqPtr.Length() > 0)
0109 #ifdef OCCT_DEBUG_UBTREE
0110       std::cout << "~NCollection_UBTreeFiller: " << Fill()
0111            << " objects added to the tree" << std::endl;
0112 #else
0113       Fill();
0114 #endif
0115   }
0116 
0117  private:
0118 
0119   // Assignment operator is made empty and private in order to
0120   // avoid warning on MSVC (C4512)
0121   void operator = (const NCollection_UBTreeFiller&) {}
0122   
0123   static Standard_Real    checkNode     (const UBTreeNode&      theNode,
0124                                          const Standard_Integer theLength,
0125                                          Standard_Integer&      theNumber);
0126 
0127 
0128  private:
0129   // ---------- PRIVATE FIELDS ----------
0130 
0131   UBTree&                    myTree;
0132   NCollection_Vector<ObjBnd> mySeqPtr;
0133   std::mt19937               myRandGen;      //!< random number generator
0134   Standard_Boolean           myIsFullRandom;
0135 };
0136 
0137 //=======================================================================
0138 //function : Fill
0139 //purpose  : 
0140 //=======================================================================
0141 
0142 template <class TheObjType, class TheBndType>
0143 Standard_Integer NCollection_UBTreeFiller<TheObjType,TheBndType>::Fill ()
0144 {
0145   Standard_Integer i, nbAdd = mySeqPtr.Length();
0146   // Fisher-Yates randomization
0147   if (myIsFullRandom)
0148   {
0149     for (i = nbAdd; i > 0; i--)
0150     {
0151       unsigned int ind = (unsigned int )myRandGen();
0152       ind = ind % i;
0153       const ObjBnd& aObjBnd = mySeqPtr(ind);
0154       myTree.Add (aObjBnd.myObj, aObjBnd.myBnd);
0155       mySeqPtr(ind) = mySeqPtr(i-1);
0156     }
0157   }
0158   else
0159   {
0160     for (i = nbAdd; i > 0; i--)
0161     {
0162       unsigned int ind = (unsigned int )myRandGen();
0163       ind = i - (ind % i) - 1;
0164       const ObjBnd& aObjBnd = mySeqPtr(ind);
0165       myTree.Add (aObjBnd.myObj, aObjBnd.myBnd);
0166       mySeqPtr(ind) = mySeqPtr(i-1);
0167     }
0168   }
0169   mySeqPtr.Clear();
0170   return nbAdd;
0171 }
0172 
0173 //=======================================================================
0174 //function : CheckTree
0175 //purpose  : 
0176 //=======================================================================
0177 
0178 template <class TheObjType, class TheBndType>
0179 Standard_Integer NCollection_UBTreeFiller<TheObjType,TheBndType>::CheckTree
0180                                         (Standard_OStream& theStream)
0181 {
0182   Standard_Integer aNumber(0);
0183   const Standard_Real aLen = checkNode (myTree.Root(), 0, aNumber);
0184   const Standard_Real num = (double) aNumber;
0185   const Standard_Real aLen1 = sqrt (aLen / num);
0186   const Standard_Real aLen0 = log(num) / log(2.);
0187   char buf[128];
0188   sprintf (buf,  "Checking UBTree:%8d leaves, balance =%7.2f",
0189            aNumber, aLen1 / aLen0);
0190   theStream << buf << std::endl;
0191   return aNumber;
0192 }
0193 
0194 //=======================================================================
0195 //function : checkNode
0196 //purpose  : 
0197 //=======================================================================
0198 
0199 template <class TheObjType, class TheBndType>
0200 Standard_Real NCollection_UBTreeFiller<TheObjType,TheBndType>::checkNode
0201   (const typename NCollection_UBTree<TheObjType, TheBndType>::TreeNode& theNode,
0202    const Standard_Integer theLength,
0203    Standard_Integer&      theNumber)
0204 {
0205   Standard_Real aLength;
0206   if (!theNode.IsLeaf())
0207     aLength = (checkNode (theNode.Child(0), theLength+1, theNumber) +
0208                checkNode (theNode.Child(1), theLength+1, theNumber));
0209   else {
0210     theNumber++;
0211     aLength = theLength * theLength;
0212   }
0213   return aLength;
0214 }
0215 
0216 #endif