1 // Created on: 2002-10-18
2 // Created by: Michael SAZONOV
3 // Copyright (c) 2002-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #ifndef NCollection_UBTreeFiller_HeaderFile
17 #define NCollection_UBTreeFiller_HeaderFile
19 #include <NCollection_UBTree.hxx>
20 #include <NCollection_Vector.hxx>
25 * This class is used to fill an UBTree in a random order.
26 * The quality of a tree is much better (from the point of view of
27 * the search time) if objects are added to it in a random order to
28 * avoid adding a chain of neerby objects one following each other.
30 * This class collects objects to be added, and then add them to the tree
33 template <class TheObjType, class TheBndType> class NCollection_UBTreeFiller
36 // ---------- PUBLIC TYPES ----------
38 //! Structure of pair (object, bnd box)
43 ObjBnd (const TheObjType& theObj, const TheBndType& theBnd)
44 : myObj(theObj), myBnd(theBnd) {}
46 : myObj(TheObjType()), myBnd(TheBndType()) {}
50 typedef NCollection_UBTree<TheObjType, TheBndType> UBTree;
51 typedef TYPENAME UBTree::TreeNode UBTreeNode;
54 // ---------- PUBLIC METHODS ----------
59 * Tree instance that is to be filled.
61 * Allocator for the Filler data.
63 * Takes effect when the number of items is large (order of 50,000). When
64 * it is True, the code uses the maximal randomization allowing a better
65 * balanced tree. If False, the randomization/tree balance are worse but
66 * the tree filling is faster due to better utilisation of CPU L1/L2 cache.
68 NCollection_UBTreeFiller (UBTree& theTree,
69 const Handle(NCollection_BaseAllocator)& theAlloc=0L,
70 const Standard_Boolean isFullRandom = Standard_True)
71 : myTree(theTree), mySeqPtr(256, theAlloc),
72 myRandGen (5489u /* == std::mt19937::default_seed, not defined in older environments, e.g, on Debian 6.0 with GCC 4.4.5 */),
73 myIsFullRandom (isFullRandom) {}
75 //! Adds a pair (theObj, theBnd) to my sequence
76 void Add (const TheObjType& theObj, const TheBndType& theBnd)
77 { mySeqPtr.Append (ObjBnd (theObj, theBnd)); }
80 * Fills the tree with the objects from my sequence. This method clears
81 * the internal buffer of added items making sure that no item would be added
84 * the number of objects added to the tree.
86 Standard_Integer Fill ();
89 * Remove all data from Filler, partculary if the Tree no more needed
90 * so the destructor of this Filler should not populate the useless Tree.
92 void Reset() { mySeqPtr.Clear(); }
95 * Check the filled tree for the total number of items and the balance
96 * outputting these results to std::ostream.
98 * the tree size (the same value is returned by method Fill()).
100 Standard_Integer CheckTree (Standard_OStream& theStream);
103 * Destructor. Fills the tree with accumulated items if they have not been
104 * passed by a previous call of method Fill().
106 ~NCollection_UBTreeFiller ()
108 if (mySeqPtr.Length() > 0)
109 #ifdef OCCT_DEBUG_UBTREE
110 std::cout << "~NCollection_UBTreeFiller: " << Fill()
111 << " objects added to the tree" << std::endl;
119 // Assignment operator is made empty and private in order to
120 // avoid warning on MSVC (C4512)
121 void operator = (const NCollection_UBTreeFiller&) {}
123 static Standard_Real checkNode (const UBTreeNode& theNode,
124 const Standard_Integer theLength,
125 Standard_Integer& theNumber);
129 // ---------- PRIVATE FIELDS ----------
132 NCollection_Vector<ObjBnd> mySeqPtr;
133 opencascade::std::mt19937 myRandGen; //!< random number generator
134 Standard_Boolean myIsFullRandom;
137 //=======================================================================
140 //=======================================================================
142 template <class TheObjType, class TheBndType>
143 Standard_Integer NCollection_UBTreeFiller<TheObjType,TheBndType>::Fill ()
145 Standard_Integer i, nbAdd = mySeqPtr.Length();
146 // Fisher-Yates randomization
148 for (i = nbAdd; i > 0; i--) {
149 unsigned int ind = myRandGen();
151 const ObjBnd& aObjBnd = mySeqPtr(ind);
152 myTree.Add (aObjBnd.myObj, aObjBnd.myBnd);
153 mySeqPtr(ind) = mySeqPtr(i-1);
156 for (i = nbAdd; i > 0; i--) {
157 unsigned int ind = myRandGen();
158 ind = i - (ind % i) - 1;
159 const ObjBnd& aObjBnd = mySeqPtr(ind);
160 myTree.Add (aObjBnd.myObj, aObjBnd.myBnd);
161 mySeqPtr(ind) = mySeqPtr(i-1);
167 //=======================================================================
168 //function : CheckTree
170 //=======================================================================
172 template <class TheObjType, class TheBndType>
173 Standard_Integer NCollection_UBTreeFiller<TheObjType,TheBndType>::CheckTree
174 (Standard_OStream& theStream)
176 Standard_Integer aNumber(0);
177 const Standard_Real aLen = checkNode (myTree.Root(), 0, aNumber);
178 const Standard_Real num = (double) aNumber;
179 const Standard_Real aLen1 = sqrt (aLen / num);
180 const Standard_Real aLen0 = log(num) / log(2.);
182 sprintf (buf, "Checking UBTree:%8d leaves, balance =%7.2f",
183 aNumber, aLen1 / aLen0);
184 theStream << buf << std::endl;
188 //=======================================================================
189 //function : checkNode
191 //=======================================================================
193 template <class TheObjType, class TheBndType>
194 Standard_Real NCollection_UBTreeFiller<TheObjType,TheBndType>::checkNode
195 (const TYPENAME NCollection_UBTree<TheObjType, TheBndType>::TreeNode& theNode,
196 const Standard_Integer theLength,
197 Standard_Integer& theNumber)
199 Standard_Real aLength;
200 if (!theNode.IsLeaf())
201 aLength = (checkNode (theNode.Child(0), theLength+1, theNumber) +
202 checkNode (theNode.Child(1), theLength+1, theNumber));
205 aLength = theLength * theLength;