Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // @(#)root/mathcore:$Id: IFunction.h 24537 2008-06-25 11:01:23Z moneta $
0002 // Authors: C. Gumpert    09/2011
0003 /**********************************************************************
0004  *                                                                    *
0005  * Copyright (c) 2011 , LCG ROOT MathLib Team                         *
0006  *                                                                    *
0007  *                                                                    *
0008  **********************************************************************/
0009 //
0010 // Implementation file for KDTree class
0011 //
0012 
0013 
0014 #ifndef KD_TREE_ICC
0015 #define KD_TREE_ICC
0016 
0017 #ifndef ROOT_Math_KDTree
0018 #error "Do not use KDTree.icc directly. #include \"KDTree.h\" instead."
0019 #endif // ROOT_Math_KDTree
0020 
0021 // STL include(s)
0022 #include <iostream>
0023 #include <functional>
0024 #include <algorithm>
0025 #include <limits>
0026 
0027 namespace ROOT
0028 {
0029    namespace Math
0030    {
0031 //______________________________________________________________________________
0032       template<class _DataPoint>
0033       KDTree<_DataPoint>::KDTree(UInt_t iBucketSize):
0034          fBucketSize(iBucketSize),
0035          fIsFrozen(false)
0036       {
0037          //standard constructor creates an empty k-d tree
0038          //
0039          //Input: iBucketSize - target population for each bin
0040          //
0041          //Note: - The actual interpretation of the bucket size as population depends on
0042          //        the chosen splitting option:
0043          //        kBinContent - iBucketSize applies to the sum of weights in each bucket
0044          //        kEffective  - iBucketSize applies to the number of effective entries in each bucket
0045          //      - As long as the tree has not been frozen, it is ensured that no bucket
0046          //        contains more than 2 x target population but there is no statement about
0047          //        the minimum bucket population.
0048          //        However, given a reasonably large bucket size with respect to characteristic
0049          //        event weights and sufficient statistics, most of the buckets will have
0050          //        a population between [0.8 * iBucketSize .. 2 * iBucketSize]
0051 
0052          // create dummy terminal node as head
0053          TerminalNode* pTerminal = new TerminalNode(iBucketSize);
0054          fHead = new HeadNode(*pTerminal);
0055          pTerminal->Parent() = fHead;
0056       }
0057 
0058 //______________________________________________________________________________
0059       template<class _DataPoint>
0060       KDTree<_DataPoint>::KDTree():
0061          fHead(0),
0062          fBucketSize(1),
0063          fIsFrozen(false)
0064       {
0065          //private standard constructor creating a not functional tree
0066          //
0067          //only used by internal function for creating copies of the tree
0068       }
0069 
0070 //______________________________________________________________________________
0071       template<class _DataPoint>
0072       KDTree<_DataPoint>::~KDTree()
0073       {
0074          //standard destructor deleting all nodes
0075          //
0076          //Note: - In case the option SetOWner(true) has been called beforehand and
0077          //        the tree is not yet frozen, all contained data point objects are
0078          //        deleted as well.
0079 
0080          delete fHead;
0081       }
0082 
0083 //______________________________________________________________________________
0084       template<class _DataPoint>
0085       inline void KDTree<_DataPoint>::EmptyBins()
0086       {
0087          //all buckets are reset
0088          //
0089          //This call results in empty buckets but the splitting structure is kept.
0090          //You can now fill the formerly created binning with 'new' data points.
0091          //In order to prevent further splitting, you might want to freeze the tree.
0092          //
0093          //Note: - In case the option SetOWner(true) has been called beforehand and
0094          //        the tree is not yet frozen, all contained data point objects are
0095          //        deleted as well.
0096 
0097          for(iterator it = First(); it != End(); ++it)
0098             it->EmptyBin();
0099       }
0100 
0101 //______________________________________________________________________________
0102       template<class _DataPoint>
0103       inline typename KDTree<_DataPoint>::iterator KDTree<_DataPoint>::End()
0104       {
0105          //return an iterator representing the end of all buckets
0106          //
0107          //This function can be used the retrieve a limiter for both sides. It
0108          //represents the 'one step after the last bin' as well as 'one step before
0109          //the first bin'. However, you should not try to increment/decrement this
0110          //iterator.
0111 
0112          return iterator(0);
0113       }
0114 
0115 //______________________________________________________________________________
0116       template<class _DataPoint>
0117       inline const typename KDTree<_DataPoint>::iterator KDTree<_DataPoint>::End() const
0118       {
0119          //return an iterator representing the end of all buckets
0120          //
0121          //This function can be used the retrieve a limiter for both sides. It
0122          //represents the 'one step after the last bin' as well as 'one step before
0123          //the first bin'. However, you should not try to increment/decrement this
0124          //iterator.
0125 
0126          return iterator(0);
0127       }
0128 
0129 //______________________________________________________________________________
0130       template<class _DataPoint>
0131       inline typename KDTree<_DataPoint>::iterator KDTree<_DataPoint>::First()
0132       {
0133          //return an iterator to the first bucket
0134          //
0135          //Note: - Buckets are not ordered to any criteria.
0136 
0137          BaseNode* pNode = fHead->Parent();
0138          while(pNode->LeftChild())
0139             pNode = pNode->LeftChild();
0140 
0141          assert(dynamic_cast<BinNode*>(pNode));
0142          return iterator((BinNode*)pNode);
0143       }
0144 
0145 //______________________________________________________________________________
0146       template<class _DataPoint>
0147       inline const typename KDTree<_DataPoint>::iterator KDTree<_DataPoint>::First() const
0148       {
0149          //return an iterator to the first bucket
0150          //
0151          //Note: - Buckets are not ordered to any criteria.
0152 
0153          BaseNode* pNode = fHead->Parent();
0154          while(pNode->LeftChild())
0155             pNode = pNode->LeftChild();
0156 
0157          assert(dynamic_cast<BinNode*>(pNode));
0158          return iterator((BinNode*)pNode);
0159       }
0160 
0161 //______________________________________________________________________________
0162       template<class _DataPoint>
0163       void KDTree<_DataPoint>::Freeze()
0164       {
0165          //freeze the current tree
0166          //
0167          //By calling this function, the current splitting information in the tree is frozen.
0168          //No further division of buckets into sub-buckets will occur.
0169          //In addition all point related information are dropped. Therefore nearest neighbor
0170          //searches or retrieving the data points from a bucket are not possible anymore.
0171          //Furthermore, no restrictions on the population in each bucket exist if the tree
0172          //is filled with further points.
0173          //
0174          //Note: - Technically it means that all TerminalNodes are converted to BinNodes
0175          //        resulting in a loss of all information related to individual data points.
0176 
0177          // do it only once
0178          if(!fIsFrozen)
0179          {
0180             std::vector<TerminalNode*> vBins;
0181             // replace all terminal nodes by bin nodes
0182             for(iterator it = First(); it != End(); ++it)
0183                vBins.push_back(it.TN());
0184 
0185             BinNode* pBin = 0;
0186             for(typename std::vector<TerminalNode*>::iterator bit = vBins.begin(); bit != vBins.end(); ++bit)
0187             {
0188                pBin = (*bit)->ConvertToBinNode();
0189                (*bit)->GetParentPointer() = pBin;
0190                pBin->Parent() = (*bit)->Parent();
0191                delete *bit;
0192             }
0193 
0194             fIsFrozen = true;
0195          }
0196       }
0197 
0198 //______________________________________________________________________________
0199       template<class _DataPoint>
0200       void KDTree<_DataPoint>::GetClosestPoints(const _DataPoint& rRef,UInt_t nPoints,
0201                                                 std::vector<std::pair<const _DataPoint*,Double_t> >& vFoundPoints) const
0202       {
0203          //returns the nPoints data points closest to the given reference point
0204          //
0205          //Input: rRef         - reference point
0206          //       nPoints      - desired number of closest points (0 < nPoints < total number of points in tree)
0207          //       vFoundPoints - vector containing all found points
0208          //
0209          //vFoundPoints contains the nPoints pairs of:
0210          // first  = pointer to found data point
0211          // second = distance between found data point and reference point
0212          //
0213          //vFoundPoints is ordered in the sense that the point closest to the reference comes first.
0214          //
0215          //Note: - This method works only if the tree has not yet been frozen.
0216 
0217          // check bad input and that tree is not frozen yet
0218          if((nPoints > 0) && (!fIsFrozen))
0219             fHead->GetClosestPoints(rRef,nPoints,vFoundPoints);
0220       }
0221 
0222 //______________________________________________________________________________
0223       template<class _DataPoint>
0224       Double_t KDTree<_DataPoint>::GetEffectiveEntries() const
0225       {
0226          //returns the total effective entries of the tree
0227          //
0228          //Note: - This is not the sum of effective entries of all buckets!
0229 
0230          Double_t fSumw = 0;
0231          Double_t fSumw2 = 0;
0232          for(iterator it = First(); it != End(); ++it)
0233          {
0234             fSumw += it->GetBinContent();
0235             fSumw2 += it->GetSumw2();
0236          }
0237 
0238          return ((fSumw2) ? fSumw * fSumw / fSumw2 : 0);
0239       }
0240 
0241 //______________________________________________________________________________
0242       template<class _DataPoint>
0243       UInt_t KDTree<_DataPoint>::GetEntries() const
0244       {
0245          //returns the number of filled data points
0246 
0247          UInt_t iPoints = 0;
0248          for(iterator it = First(); it != End(); ++it)
0249             iPoints += it->GetEntries();
0250 
0251          return iPoints;
0252       }
0253 
0254 //______________________________________________________________________________
0255       template<class _DataPoint>
0256       KDTree<_DataPoint>* KDTree<_DataPoint>::GetFrozenCopy()
0257       {
0258          //returns a frozen copy of this k-d tree
0259          //
0260          //Note: - The current tree remains unchanged.
0261          //      - The new tree is owned by the user (-> you should invoke 'delete' if you do not need it anymore)!
0262 
0263          KDTree<_DataPoint>* pTree = new KDTree<_DataPoint>();
0264          pTree->fBucketSize = fBucketSize;
0265          pTree->fHead = fHead->Clone();
0266          pTree->fIsFrozen = true;
0267 
0268          return pTree;
0269       }
0270 
0271 //______________________________________________________________________________
0272       template<class _DataPoint>
0273       UInt_t KDTree<_DataPoint>::GetNBins() const
0274       {
0275          //returns the number of buckets
0276 
0277          UInt_t iBins = 0;
0278          for(iterator it = First(); it != End(); ++it)
0279             ++iBins;
0280 
0281          return iBins;
0282       }
0283 
0284 //______________________________________________________________________________
0285       template<class _DataPoint>
0286       void KDTree<_DataPoint>::GetPointsWithinDist(const _DataPoint& rRef,value_type fDist,
0287                                                    std::vector<const _DataPoint*>& vFoundPoints) const
0288       {
0289          //returns all data points within a given distance around the reference point
0290          //
0291          //Input: rRef         - reference point
0292          //       fDist        - radius of sphere around reference point (0 < fDist)
0293          //       vFoundPoints - vector to store the results
0294          //
0295          //vFoundPoints contains the pointers to all data points in the specified sphere.
0296          //The points are NOT ordered according to their distance.
0297          //
0298          //Note - This method works only if the tree has not yet been frozen.
0299          //     - Distance is defined as euclidean distance in a k-dimensional space.
0300 
0301          // valid distance given and tree not frozen yet
0302          if((fDist > 0) && (!fIsFrozen))
0303             fHead->GetPointsWithinDist(rRef,fDist,vFoundPoints);
0304       }
0305 
0306 //______________________________________________________________________________
0307       template<class _DataPoint>
0308       Double_t KDTree<_DataPoint>::GetTotalSumw() const
0309       {
0310          //returns the total sum of weights
0311 
0312          Double_t fSumw = 0;
0313          for(iterator it = First(); it != End(); ++it)
0314             fSumw += it->GetSumw();
0315 
0316          return fSumw;
0317       }
0318 
0319 //______________________________________________________________________________
0320       template<class _DataPoint>
0321       Double_t KDTree<_DataPoint>::GetTotalSumw2() const
0322       {
0323          //returns the total sum of weights^2
0324 
0325          Double_t fSumw2 = 0;
0326          for(iterator it = First(); it != End(); ++it)
0327             fSumw2 += it->GetSumw2();
0328 
0329          return fSumw2;
0330       }
0331 
0332 //______________________________________________________________________________
0333       template<class _DataPoint>
0334       inline typename KDTree<_DataPoint>::iterator KDTree<_DataPoint>::Last()
0335       {
0336          //returns an iterator to the last bucket
0337          //
0338          //Note: - Buckets are not ordered to any criteria.
0339 
0340          BaseNode* pNode = fHead->Parent();
0341          while(pNode->RightChild())
0342             pNode = pNode->RightChild();
0343 
0344          assert(dynamic_cast<TerminalNode*>(pNode));
0345          return iterator((TerminalNode*)pNode);
0346       }
0347 
0348 //______________________________________________________________________________
0349       template<class _DataPoint>
0350       inline const typename KDTree<_DataPoint>::iterator KDTree<_DataPoint>::Last() const
0351       {
0352          //returns an iterator to the last bucket
0353          //
0354          //Note: - Buckets are not ordered to any criteria.
0355 
0356          BaseNode* pNode = fHead->Parent();
0357          while(pNode->RightChild())
0358             pNode = pNode->RightChild();
0359 
0360          assert(dynamic_cast<BinNode*>(pNode));
0361          return iterator((BinNode*)pNode);
0362       }
0363 
0364 //______________________________________________________________________________
0365       template<class _DataPoint>
0366       void KDTree<_DataPoint>::Reset()
0367       {
0368          //resets the tree
0369          //
0370          //Afterwards the tree is completely empty and all splitting information is lost.
0371          //
0372          //Note: - In case the option SetOWner(true) has been called beforehand and
0373          //        the tree is not yet frozen, all contained data point objects are
0374          //        deleted as well.
0375          //      - The 'frozen' status is reset to false. Otherwise you won't be able to
0376          //        create splittings and the tree would consist of only one large bucket.
0377 
0378          // delete current tree
0379          delete fHead->Parent();
0380          // create new (and empty) top bucket
0381          TerminalNode* pTerminal = new TerminalNode(fBucketSize);
0382          pTerminal->Parent() = fHead;
0383          fHead->Parent() = pTerminal;
0384 
0385          // reset 'freeze' status
0386          fIsFrozen = false;
0387       }
0388 
0389 //______________________________________________________________________________
0390       template<class _DataPoint>
0391       void KDTree<_DataPoint>::SetOwner(Bool_t bIsOwner)
0392       {
0393          //specifies the ownership of data points
0394          //
0395          //Input: bIsOwner - true: data points are located on the heap and the ownership
0396          //                        is transferred to the tree object
0397          //                  false: the data points are not owned by the tree
0398          //
0399          //Note: - This function has no effect if the tree is already frozen.
0400 
0401          if(!fIsFrozen)
0402          {
0403             for(iterator it = First(); it != End(); ++it)
0404                it.TN()->SetOwner(bIsOwner);
0405          }
0406       }
0407 
0408 //______________________________________________________________________________
0409       template<class _DataPoint>
0410       void KDTree<_DataPoint>::SetSplitOption(eSplitOption opt)
0411       {
0412          //sets the splitting option for the buckets
0413          //
0414          //Buckets are split into two sub-buckets if their population reaches twice the
0415          //given bucket size. The definition of population depends on the chosen splitting
0416          //option:
0417          //kBinContent = population is the sum of weights
0418          //kEffective  = population is the number of effective entries
0419          //
0420          //Note: - In principle it possible to change the splitting mode while filling the tree.
0421          //        However, this should be avoided to ensure an optimal splitting.
0422          //      - This function has no effect if the tree is already frozen.
0423 
0424          if(!fIsFrozen)
0425          {
0426             for(iterator it = First(); it != End(); ++it)
0427                it.TN()->SetSplitOption(opt);
0428          }
0429       }
0430 
0431 //______________________________________________________________________________
0432       template<class _DataPoint>
0433       bool KDTree<_DataPoint>::ComparePoints::operator()(const _DataPoint* pFirst,const _DataPoint* pSecond) const
0434       {
0435          //compares two points along set axis
0436          //
0437          //Uses the internal comparison axis of the ComparePoints object to evaluate:
0438          //
0439          // pFirst[Axis] < pSecond[Axis]
0440          //
0441          //Note: - The template class _DataPoint has to provide a static function:
0442          //
0443          //        static UInt_t _DataPoint::Dimension()
0444          //
0445          //        returning the dimensionality of the data point.
0446          //      - The dimensionality of the two data points is higher than the currently
0447          //        set comparison axis.
0448 
0449          assert(pFirst && pSecond && (fAxis < KDTree<_DataPoint>::Dimension()));
0450 
0451          return (pFirst->GetCoordinate(fAxis) < pSecond->GetCoordinate(fAxis));
0452       }
0453 
0454 //______________________________________________________________________________
0455       template<class _DataPoint>
0456       bool KDTree<_DataPoint>::Cut::operator<(const _DataPoint& rPoint) const
0457       {
0458          //comapares a point with the given cut
0459          //
0460          // this cut value < rPoint.GetCoordinate(this cut axis)
0461          //
0462          //Note: - The template class _DataPoint has to provide a static function:
0463          //
0464          //        static UInt_t _DataPoint::Dimension()
0465          //
0466          //        returning the dimensionality of the data point.
0467          //      - The dimensionality of the given data point is higher than the cut
0468          //        axis.
0469 
0470          assert(Dimension() > fAxis);
0471          return (fCutValue < rPoint.GetCoordinate(fAxis));
0472       }
0473 
0474 //______________________________________________________________________________
0475       template<class _DataPoint>
0476       bool KDTree<_DataPoint>::Cut::operator>(const _DataPoint& rPoint) const
0477       {
0478          //compares a point with the given cut
0479          //
0480          // this cut value > rPoint.GetCoordinate(this cut axis)
0481          //
0482          //Note: - The template class _DataPoint has to provide a static function:
0483          //
0484          //        static UInt_t _DataPoint::Dimension()
0485          //
0486          //        returning the dimensionality of the data point.
0487          //      - The dimensionality of the given data point is higher than the cut
0488          //        axis.
0489 
0490          assert(Dimension() > fAxis);
0491          return (fCutValue > rPoint.GetCoordinate(fAxis));
0492       }
0493 
0494 //______________________________________________________________________________
0495       template<class _DataPoint>
0496       KDTree<_DataPoint>::BaseNode::BaseNode(BaseNode* pParent):
0497          fParent(pParent),
0498          fLeftChild(0),
0499          fRightChild(0)
0500       {
0501          //standard constructor
0502       }
0503 
0504 //______________________________________________________________________________
0505       template<class _DataPoint>
0506       KDTree<_DataPoint>::BaseNode::~BaseNode()
0507       {
0508          //standard destructor
0509          //
0510          //Note: - both children are deleted but no pointer rearrangement is done
0511          //        -> should not be a problem as long as you do not try to rely on
0512          //           tree internal information
0513 
0514          delete LeftChild();
0515          delete RightChild();
0516       }
0517 
0518 //______________________________________________________________________________
0519       template<class _DataPoint>
0520       typename KDTree<_DataPoint>::BaseNode*& KDTree<_DataPoint>::BaseNode::GetParentPointer()
0521       {
0522          //returns a reference to the pointer from the parent node to the current node
0523          //
0524          //Note: - This should never be called for the head node (as it is the head!)
0525 
0526          assert(!IsHeadNode());
0527 
0528          if(Parent()->Parent() == this)
0529             return Parent()->Parent();
0530          if(Parent()->LeftChild() == this)
0531             return Parent()->LeftChild();
0532          if(Parent()->RightChild() == this)
0533             return Parent()->RightChild();
0534 
0535          // should never reach this line
0536          assert(false);
0537          return Parent();  // to fix a warning statement
0538       }
0539 
0540 //______________________________________________________________________________
0541       template<class _DataPoint>
0542       bool KDTree<_DataPoint>::BaseNode::IsLeftChild() const
0543       {
0544          //checks whether the current node is a left node
0545          //
0546          //Note: - returns false in the case of the head node (which is no child at all)
0547 
0548          if(Parent()->IsHeadNode())
0549             return false;
0550          else
0551             return (Parent()->LeftChild() == this);
0552       }
0553 
0554 //______________________________________________________________________________
0555       template<class _DataPoint>
0556       typename KDTree<_DataPoint>::HeadNode* KDTree<_DataPoint>::HeadNode::Clone()
0557       {
0558          //creates an identical copy
0559          //
0560          //Note: - The Clone() function is propagated to the whole tree -> the returned
0561          //        pointer is the head node of a complete new tree.
0562 
0563          BaseNode* pParent = Parent()->Clone();
0564          HeadNode* pHead = new HeadNode(*pParent);
0565          pParent->Parent() = pHead;
0566 
0567          return pHead;
0568       }
0569 
0570 //______________________________________________________________________________
0571       template<class _DataPoint>
0572       inline void KDTree<_DataPoint>::HeadNode::GetClosestPoints(const _DataPoint& rRef,UInt_t nPoints,
0573                                                                  std::vector<std::pair<const _DataPoint*,Double_t> >& vFoundPoints) const
0574       {
0575          Parent()->GetClosestPoints(rRef,nPoints,vFoundPoints);
0576       }
0577 
0578 //______________________________________________________________________________
0579       template<class _DataPoint>
0580       inline void KDTree<_DataPoint>::HeadNode::GetPointsWithinDist(const _DataPoint& rRef,value_type fDist,
0581                                                                     std::vector<const _DataPoint*>& vFoundPoints) const
0582       {
0583          Parent()->GetPointsWithinDist(rRef,fDist,vFoundPoints);
0584       }
0585 
0586 //______________________________________________________________________________
0587       template<class _DataPoint>
0588       KDTree<_DataPoint>::SplitNode::SplitNode(UInt_t iAxis,Double_t fCutValue,BaseNode& rLeft,
0589                                                BaseNode& rRight,BaseNode* pParent):
0590          BaseNode(pParent),
0591          fCut(new Cut(iAxis,fCutValue))
0592       {
0593          //standard constructor for spitting node which represents a splitting hyperplane
0594          //
0595          //Input: iAxis     - axis on which the split is performed
0596          //       fCutValue - cut value
0597          //       rLeft     - left sub-bucket
0598          //       rRight    - right sub-bucket
0599          //       pParent   - optional pointer to parent node
0600          //
0601          //Note: - As a split node can never be a leaf, always the two child nodes has to
0602          //        be passed at construction time.
0603 
0604          this->LeftChild() = &rLeft;
0605          this->RightChild() = &rRight;
0606       }
0607 
0608 //______________________________________________________________________________
0609       template<class _DataPoint>
0610       KDTree<_DataPoint>::SplitNode::~SplitNode()
0611       {
0612          // standard destructor
0613 
0614          delete fCut;
0615       }
0616 
0617 //______________________________________________________________________________
0618       template<class _DataPoint>
0619       typename KDTree<_DataPoint>::SplitNode* KDTree<_DataPoint>::SplitNode::Clone()
0620       {
0621          //creates a direct copy of this node
0622          //
0623          //This also involves the copying of the child nodes.
0624 
0625          BaseNode* pLeft = this->LeftChild()->Clone();
0626          BaseNode* pRight = this->RightChild()->Clone();
0627 
0628          SplitNode* pSplit = new SplitNode(fCut->GetAxis(),fCut->GetCutValue(),*pLeft,*pRight);
0629 
0630          pLeft->Parent() = pSplit;
0631          pRight->Parent() = pSplit;
0632 
0633          return pSplit;
0634       }
0635 
0636 //______________________________________________________________________________
0637       template<class _DataPoint>
0638       const typename KDTree<_DataPoint>::BinNode* KDTree<_DataPoint>::SplitNode::FindNode(const _DataPoint& rPoint) const
0639       {
0640          //finds bin node containing the given reference point
0641 
0642          // pPoint < cut -> left sub tree
0643          if(*fCut > rPoint)
0644             return this->LeftChild()->FindNode(rPoint);
0645          // pPoint >= cut -> right sub tree
0646          else
0647             return this->RightChild()->FindNode(rPoint);
0648       }
0649 
0650 //______________________________________________________________________________
0651       template<class _DataPoint>
0652       void KDTree<_DataPoint>::SplitNode::GetClosestPoints(const _DataPoint& rRef,UInt_t nPoints,
0653                                                            std::vector<std::pair<const _DataPoint*,Double_t> >& vFoundPoints) const
0654       {
0655          //finds the closest points around the given reference point
0656          //
0657          //Input: rRef         - reference point
0658          //       nPoints      - number of points to look for (should be less than the total number of points in the tree)
0659          //       vFoundPoints - vector in which the result is stored as pair <pointer to found data point,distance to reference point>
0660          //
0661          //Note: vFoundPoints is ordered in the sense that the found point closest to the reference point comes first.
0662 
0663          // rRef < cut -> left sub tree
0664          if(*fCut > rRef)
0665          {
0666             this->LeftChild()->GetClosestPoints(rRef,nPoints,vFoundPoints);
0667 
0668             // number of found points lower than wanted number of points
0669             // or: sphere with (radius = largest distance between rRef and vFoundPoints) intersects the splitting plane
0670             // --> look also in right sub bucket
0671             if((vFoundPoints.size() < nPoints) || (vFoundPoints.back().second > fabs(rRef.GetCoordinate(fCut->GetAxis()) - fCut->GetCutValue())))
0672                this->RightChild()->GetClosestPoints(rRef,nPoints,vFoundPoints);
0673          }
0674          // rRef >= cut -> right sub tree
0675          else
0676          {
0677             this->RightChild()->GetClosestPoints(rRef,nPoints,vFoundPoints);
0678 
0679             // number of found points lower than wanted number of points
0680             // or: sphere with (radius = largest distance between rRef and vFoundPoints) intersects the splitting plane
0681             // --> look also in left sub bucket
0682             if((vFoundPoints.size() < nPoints) || (vFoundPoints.back().second > fabs(rRef.GetCoordinate(fCut->GetAxis()) - fCut->GetCutValue())))
0683                this->LeftChild()->GetClosestPoints(rRef,nPoints,vFoundPoints);
0684          }
0685       }
0686 
0687 //______________________________________________________________________________
0688       template<class _DataPoint>
0689       void KDTree<_DataPoint>::SplitNode::GetPointsWithinDist(const _DataPoint& rRef,value_type fDist,
0690                                                               std::vector<const _DataPoint*>& vFoundPoints) const
0691       {
0692          //returns the points within a certain distance around the reference point
0693          //
0694          //Input: rRef         - reference point
0695          //       fDist        - radius of sphere to scan ( > 0)
0696          //       vFoundPoints - vector in which all found points are stored
0697          //
0698          //Note: vFoundPoints ist NOT ordered.
0699 
0700          // does the sphere around rRef intersect the splitting plane?
0701          // no -> check only points in sub bucket which rRef belongs to
0702          if(fabs(rRef.GetCoordinate(fCut->GetAxis()) - fCut->GetCutValue()) > fDist)
0703          {
0704             // rRef < cut -> left sub tree
0705             if(*fCut > rRef)
0706                this->LeftChild()->GetPointsWithinDist(rRef,fDist,vFoundPoints);
0707             // rRef >= cut -> right sub tree
0708             else
0709                this->RightChild()->GetPointsWithinDist(rRef,fDist,vFoundPoints);
0710          }
0711          // yes -> check points in both sub buckets
0712          else
0713          {
0714             this->RightChild()->GetPointsWithinDist(rRef,fDist,vFoundPoints);
0715             this->LeftChild()->GetPointsWithinDist(rRef,fDist,vFoundPoints);
0716          }
0717       }
0718 
0719 //______________________________________________________________________________
0720       template<class _DataPoint>
0721       inline Bool_t KDTree<_DataPoint>::SplitNode::Insert(const _DataPoint& rPoint)
0722       {
0723          //inserts a new data point in the tree
0724 
0725          // pPoint < cut -> left sub tree
0726          if(*fCut > rPoint)
0727             return this->LeftChild()->Insert(rPoint);
0728          // pPoint >= cut -> right sub tree
0729          else
0730             return this->RightChild()->Insert(rPoint);
0731       }
0732 
0733 //______________________________________________________________________________
0734       template<class _DataPoint>
0735       void KDTree<_DataPoint>::SplitNode::Print(int iRow) const
0736       {
0737          //prints some information about the current node
0738 
0739          std::cout << "SplitNode at " << this << " in row " << iRow << std::endl;
0740          std::cout << "cut on " << fCut->GetCutValue() << " at axis " << fCut->GetAxis() << std::endl;
0741 
0742          this->LeftChild()->Print(iRow+1);
0743          this->RightChild()->Print(iRow+1);
0744       }
0745 
0746 //______________________________________________________________________________
0747       template<class _DataPoint>
0748       KDTree<_DataPoint>::BinNode::BinNode(BaseNode* pParent):
0749          BaseNode(pParent),
0750          fBoundaries(std::vector<tBoundary>(Dimension(),std::make_pair(0,0))),
0751          fSumw(0),
0752          fSumw2(0),
0753          fEntries(0)
0754       {
0755          //standard constructor
0756       }
0757 
0758 //______________________________________________________________________________
0759       template<class _DataPoint>
0760       KDTree<_DataPoint>::BinNode::BinNode(const BinNode& copy):
0761          BaseNode(),
0762          fBoundaries(copy.fBoundaries),
0763          fSumw(copy.fSumw),
0764          fSumw2(copy.fSumw2),
0765          fEntries(copy.fEntries)
0766       {
0767          //copy constructor
0768          //
0769          //Note: - The resulting bin node is NOT connected to any other node
0770          //        -> it is not part of any tree
0771 
0772          this->Parent() = 0;
0773          this->LeftChild() = 0;
0774          this->RightChild() = 0;
0775       }
0776 
0777 //______________________________________________________________________________
0778       template<class _DataPoint>
0779       typename KDTree<_DataPoint>::BinNode* KDTree<_DataPoint>::BinNode::Clone()
0780       {
0781          //creates identical copy which is not part of the tree anymore
0782 
0783          return new BinNode(*this);
0784       }
0785 
0786 //______________________________________________________________________________
0787       template<class _DataPoint>
0788       void KDTree<_DataPoint>::BinNode::EmptyBin()
0789       {
0790          //resets bin content, sumw, asumw2 and entries
0791 
0792          fSumw2 = fSumw = 0;
0793          fEntries = 0;
0794       }
0795 
0796 //______________________________________________________________________________
0797       template<class _DataPoint>
0798       typename KDTree<_DataPoint>::BinNode& KDTree<_DataPoint>::BinNode::operator=(const BinNode& rhs)
0799       {
0800          //assignment operator
0801          //
0802          //Note: - Should not be used because it can lead to inconsistencies with respect
0803          //        bin boundaries.
0804 
0805          fBoundaries = rhs.fBoundaries;
0806          fSumw = rhs.fSumw;
0807          fSumw2 = rhs.fSumw2;
0808          fEntries = rhs.fEntries;
0809          return *this;
0810       }
0811 
0812 //______________________________________________________________________________
0813       template<class _DataPoint>
0814       const typename KDTree<_DataPoint>::BinNode* KDTree<_DataPoint>::BinNode::FindNode(const _DataPoint& rPoint) const
0815       {
0816          //finds bin node containing the given reference point
0817 
0818          if(IsInBin(rPoint))
0819             return this;
0820          else
0821             return 0;
0822       }
0823 
0824 //______________________________________________________________________________
0825       template<class _DataPoint>
0826       _DataPoint KDTree<_DataPoint>::BinNode::GetBinCenter() const
0827       {
0828          //returns the bin center of the current node
0829          //
0830          //Note: - The bin center is defined as
0831          //        coordinate i = 0.5 * (lower bound i + upper bound i)
0832 
0833          _DataPoint rPoint;
0834 
0835          for(UInt_t k = 0; k < Dimension(); ++k)
0836             rPoint.SetCoordinate(k,0.5 * (fBoundaries.at(k).first + fBoundaries.at(k).second));
0837 
0838          return rPoint;
0839       }
0840 
0841 //______________________________________________________________________________
0842       template<class _DataPoint>
0843       Double_t KDTree<_DataPoint>::BinNode::GetVolume() const
0844       {
0845          //returns the volume of the current bin
0846          //
0847          //Note: - The volume is defined as
0848          //        vol = product over i (upper bound i - lower bound i)
0849 
0850          Double_t dVol = 1;
0851          for(typename std::vector<tBoundary>::const_iterator it = fBoundaries.begin(); it != fBoundaries.end(); ++it)
0852             dVol *= (it->second - it->first);
0853 
0854          return dVol;
0855       }
0856 
0857 
0858 //______________________________________________________________________________
0859       template<class _DataPoint>
0860       Bool_t KDTree<_DataPoint>::BinNode::Insert(const _DataPoint& rPoint)
0861       {
0862          //inserts a new data point in this bin
0863 
0864          if(IsInBin(rPoint))
0865          {
0866             ++fEntries;
0867             fSumw += rPoint.GetWeight();
0868             fSumw2 += pow(rPoint.GetWeight(),2);
0869 
0870             return true;
0871          }
0872          else
0873             return false;
0874       }
0875 
0876 //______________________________________________________________________________
0877       template<class _DataPoint>
0878       Bool_t KDTree<_DataPoint>::BinNode::IsInBin(const _DataPoint& rPoint) const
0879       {
0880          //checks whether the given point is inside the boundaries of this bin
0881 
0882          for(UInt_t k = 0; k < Dimension(); ++k)
0883             if((rPoint.GetCoordinate(k) < fBoundaries.at(k).first) || (fBoundaries.at(k).second < rPoint.GetCoordinate(k)))
0884                return false;
0885 
0886          return true;
0887       }
0888 
0889 //______________________________________________________________________________
0890       template<class _DataPoint>
0891       void KDTree<_DataPoint>::BinNode::Print(int) const
0892       {
0893          //prints some information about this bin node
0894 
0895          std::cout << "BinNode at " << this << std::endl;
0896          std::cout << "containing " << GetEntries() << " entries" << std::endl;
0897          std::cout << "sumw = " << GetBinContent() << " sumw2 = " << GetSumw2() << " => effective entries = " << GetEffectiveEntries() << std::endl;
0898          std::cout << "volume = " << GetVolume() << " and bin center at (";
0899          _DataPoint rBinCenter = GetBinCenter();
0900          for(UInt_t dim = 0; dim < Dimension(); ++dim)
0901          {
0902             std::cout << rBinCenter.GetCoordinate(dim);
0903             if(dim < Dimension() -1)
0904                std::cout << ",";
0905          }
0906          std::cout << ")" << std::endl;
0907          std::cout << "boundaries are ";
0908          for(typename std::vector<tBoundary>::const_iterator it = fBoundaries.begin(); it != fBoundaries.end(); ++it)
0909             std::cout << "(" << it->first << " ... " << it->second << ") ";
0910          std::cout << std::endl;
0911       }
0912 
0913 //______________________________________________________________________________
0914       template<class _DataPoint>
0915       KDTree<_DataPoint>::TerminalNode::TerminalNode(Double_t iBucketSize,BaseNode* pParent):
0916          BinNode(pParent),
0917          fOwnData(false),
0918          fSplitOption(kEffective),
0919          fBucketSize(iBucketSize),
0920          fSplitAxis(0)
0921       {
0922          //standard constructor
0923          //
0924          //Input: iBucketSize - desired bucket size
0925          //       pParent     - pointer to parent node (optional)
0926          //
0927          //Note: - The bucket size has to be positive.
0928          //      - The standard split option is kEffective.
0929          //      - By default the data points are not owned by the tree.
0930 
0931          assert(fBucketSize > 0);
0932       }
0933 
0934 //______________________________________________________________________________
0935       template<class _DataPoint>
0936       KDTree<_DataPoint>::TerminalNode::TerminalNode(Double_t iBucketSize,UInt_t iSplitAxis,data_it first,data_it end):
0937          BinNode(),
0938          fOwnData(false),
0939          fSplitOption(kEffective),
0940          fBucketSize(iBucketSize),
0941          fSplitAxis(iSplitAxis % Dimension()),
0942          fDataPoints(std::vector<const _DataPoint*>(first,end))
0943       {
0944          //internal constructor used for splitting
0945          //
0946          //Input: iBucketSize - desired bucket size
0947          //       iSplitAxis  - axis for next splitting
0948          //       first,end   - iterators pointing to the beginning and end of data points
0949          //                     which are copied to this TerminalNode
0950 
0951          // recalculate sumw and sumw2
0952          for(data_it it = fDataPoints.begin(); it != fDataPoints.end(); ++it)
0953          {
0954             this->fSumw += (*it)->GetWeight();
0955             this->fSumw2 += pow((*it)->GetWeight(),2);
0956          }
0957 
0958          this->fEntries = fDataPoints.size();
0959       }
0960 
0961 //______________________________________________________________________________
0962       template<class _DataPoint>
0963       KDTree<_DataPoint>::TerminalNode::~TerminalNode()
0964       {
0965          //standard destructor
0966          //
0967          //Note: - If fOwnData is set, all associated data point objects are deleted
0968 
0969          if(fOwnData)
0970          {
0971             for(typename std::vector<const _DataPoint*>::iterator it = fDataPoints.begin();
0972                 it != fDataPoints.end(); ++it)
0973                delete *it;
0974          }
0975       }
0976 
0977 //______________________________________________________________________________
0978       template<class _DataPoint>
0979       typename KDTree<_DataPoint>::BinNode* KDTree<_DataPoint>::TerminalNode::ConvertToBinNode()
0980       {
0981          //creates a new BinNode with information of the TerminalNode
0982          //
0983          //The returned BinNode contains all information of this TerminalNode except the
0984          //point-related information.
0985          //
0986          //Note: - The returned node is not owned by the tree but the user as to take care of it.
0987 
0988          UpdateBoundaries();
0989          BinNode* pBin = new BinNode(*this);
0990 
0991          return pBin;
0992       }
0993 
0994 //______________________________________________________________________________
0995       template<class _DataPoint>
0996       void KDTree<_DataPoint>::TerminalNode::EmptyBin()
0997       {
0998          //resets the bin content and removes all data points
0999          //
1000          //Note: - If fOwnData is set, all associated data points are deleted.
1001 
1002          // delete data points
1003          if(fOwnData)
1004          {
1005             for(typename std::vector<const _DataPoint*>::iterator it = fDataPoints.begin();
1006                 it != fDataPoints.end(); ++it)
1007                delete *it;
1008          }
1009          fDataPoints.clear();
1010          UpdateBoundaries();
1011          BinNode::EmptyBin();
1012       }
1013 //______________________________________________________________________________
1014       template<class _DataPoint>
1015 #ifdef _AIX
1016       void KDTree<_DataPoint>::TerminalNode::GetBoundaries() const { }
1017 #else
1018       const std::vector<typename KDTree<_DataPoint>::TerminalNode::tBoundary>& KDTree<_DataPoint>::TerminalNode::GetBoundaries() const
1019       {
1020          //returns the boundaries of this TerminalNode
1021          //
1022          //Note: - In a high-dimensional space most of the nodes are bounded only on
1023          //        one side due to a split. One-sided intervals would result in an
1024          //        infinite volume of the bin which is not the desired behaviour.
1025          //        Therefore the following convention is used for determining the
1026          //        boundaries:
1027          //        If a node is not restricted along one axis on one/both side(s) due
1028          //        to a split, the corresponding upper/lower boundary is set to
1029          //        the minimum/maximum coordinate along this axis of all contained
1030          //        data points.
1031          //        This procedure maximises the density in the bins.
1032 
1033          const_cast<TerminalNode*>(this)->UpdateBoundaries();
1034 
1035          return BinNode::GetBoundaries();
1036       }
1037 #endif
1038 //______________________________________________________________________________
1039       template<class _DataPoint>
1040       void KDTree<_DataPoint>::TerminalNode::GetClosestPoints(const _DataPoint& rRef,UInt_t nPoints,
1041                                                               std::vector<std::pair<const _DataPoint*,Double_t> >& vFoundPoints) const
1042       {
1043          //finds the closest points around the given reference point
1044          //
1045          //Input: rRef         - reference point
1046          //       nPoints      - number of points to look for (should be less than the total number of points in the tree)
1047          //       vFoundPoints - vector in which the result is stored as pair <pointer to found data point,distance to reference point>
1048          //
1049          //Note: vFoundPoints is ordered in the sense that the found point closest to the reference point comes first.
1050 
1051          // store maximal distance so far if desired number of points already found
1052          value_type fMaxDist = (vFoundPoints.size() < nPoints) ? std::numeric_limits<value_type>::max() : vFoundPoints.back().second;
1053          value_type fDist;
1054          typedef typename std::vector<std::pair<const _DataPoint*,Double_t> >::iterator t_pit;
1055 
1056          // loop over all points and check distances
1057          for(typename std::vector<const _DataPoint*>::const_iterator it = fDataPoints.begin(); it != fDataPoints.end(); ++it)
1058          {
1059             fDist = (*it)->Distance(rRef);
1060             // fDist < fMaxDist -> insert
1061             if(fDist < fMaxDist)
1062             {
1063                // find position at which the current point should be inserted
1064                t_pit pit = vFoundPoints.begin();
1065                while(pit != vFoundPoints.end())
1066                {
1067                   if(pit->second > fDist)
1068                      break;
1069                   else
1070                      ++pit;
1071                }
1072 
1073                vFoundPoints.insert(pit,std::make_pair(*it,fDist));
1074                // truncate vector of found points at nPoints
1075                if(vFoundPoints.size() > nPoints)
1076                   vFoundPoints.resize(nPoints);
1077                // update maximal distance
1078                fMaxDist = (vFoundPoints.size() < nPoints) ? vFoundPoints.back().second : std::numeric_limits<value_type>::max();
1079             }
1080          }
1081       }
1082 
1083 //______________________________________________________________________________
1084       template<class _DataPoint>
1085       void KDTree<_DataPoint>::TerminalNode::GetPointsWithinDist(const _DataPoint& rRef,value_type fDist,
1086                                                                  std::vector<const _DataPoint*>& vFoundPoints) const
1087       {
1088          //returns the points within a certain distance around the reference point
1089          //
1090          //Input: rRef         - reference point
1091          //       fDist        - radius of sphere to scan ( > 0)
1092          //       vFoundPoints - vector in which all found points are stored
1093          //
1094          //Note: vFoundPoints ist NOT ordered.
1095 
1096          // loop over all points and check distances
1097          for(typename std::vector<const _DataPoint*>::const_iterator it = fDataPoints.begin(); it != fDataPoints.end(); ++it)
1098          {
1099             if((*it)->Distance(rRef) <= fDist)
1100                vFoundPoints.push_back(*it);
1101          }
1102       }
1103 
1104 //______________________________________________________________________________
1105       template<class _DataPoint>
1106       Bool_t KDTree<_DataPoint>::TerminalNode::Insert(const _DataPoint& rPoint)
1107       {
1108          //inserts a new data point in this bin
1109          //
1110          //Note: - If the population of this TerminalNode exceeds the limit of
1111          //        2 x fBucketSize, the node is split using the Split() function.
1112 
1113          // store pointer to data point
1114          fDataPoints.push_back(&rPoint);
1115 
1116          // update weights
1117          this->fSumw += rPoint.GetWeight();
1118          this->fSumw2 += pow(rPoint.GetWeight(),2);
1119          ++this->fEntries;
1120 
1121          // split terminal node if necessary
1122          switch(fSplitOption)
1123          {
1124          case kEffective:
1125             if(this->GetEffectiveEntries() > 2 * fBucketSize)
1126                Split();
1127             break;
1128          case kBinContent:
1129             if(this->GetSumw() > 2 * fBucketSize)
1130                Split();
1131             break;
1132          default: assert(false);
1133          }
1134 
1135          return true;
1136       }
1137 
1138 //______________________________________________________________________________
1139       template<class _DataPoint>
1140       void KDTree<_DataPoint>::TerminalNode::Print(int iRow) const
1141       {
1142          //prints some information about this TerminalNode
1143 
1144          std::cout << "TerminalNode at " << this << " in row " << iRow << std::endl;
1145          const_cast<TerminalNode*>(this)->UpdateBoundaries();
1146          BinNode::Print(iRow);
1147          std::cout << "next split axis: " << fSplitAxis << std::endl << std::endl;
1148          for(const_data_it it = fDataPoints.begin(); it != fDataPoints.end(); ++it)
1149          {
1150             std::cout << "(";
1151             for(UInt_t i = 0; i < Dimension(); ++i)
1152             {
1153                std::cout << (*it)->GetCoordinate(i);
1154                if(i != Dimension() - 1)
1155                   std::cout << ",";
1156             }
1157             std::cout << "), w = " << (*it)->GetWeight() << std::endl;
1158          }
1159 
1160          std::cout << std::endl;
1161       }
1162 
1163 //______________________________________________________________________________
1164       template<class _DataPoint>
1165       void KDTree<_DataPoint>::TerminalNode::Split()
1166       {
1167          //splits this TerminalNode
1168          //
1169          //A new SplitNode containing the split axis and split value is created. It
1170          //is placed at the current position of this TerminalNode in the tree.
1171          //The data points in this node are divided into two groups according to
1172          //the splitting axis and value. From the second half a new TerminalNode is created.
1173          //
1174          //Sketch:               SplitNode
1175          //                     |         |
1176          //                    ...   current TerminalNode (which is split)
1177          //
1178          //                         |
1179          //                         V
1180          //
1181          //                      SplitNode
1182          //                     |         |
1183          //                    ...     new SplitNode
1184          //                           |             |
1185          //                current TerminalNode   new TerminalNode
1186          //                (modified)
1187 
1188          data_it cut;
1189          switch(fSplitOption)
1190          {
1191          case kEffective: cut = SplitEffectiveEntries(); break;
1192          case kBinContent: cut = SplitBinContent(); break;
1193          default: assert(false);
1194          }
1195 
1196          // store split value
1197          value_type fSplitValue = (*cut)->GetCoordinate(fSplitAxis);
1198          //create second terminal node with second part of (unsorted vector)
1199          TerminalNode* pNew = new TerminalNode(fBucketSize,fSplitAxis+1,cut,fDataPoints.end());
1200          // copy options
1201          pNew->SetOwner(fOwnData);
1202          pNew->SetSplitOption(fSplitOption);
1203 
1204          // remove the copied elements from this bucket
1205          fDataPoints.erase(cut,fDataPoints.end());
1206          // recalculate sumw and sumw2
1207          this->fSumw = this->fSumw2 = 0;
1208          for(data_it it = fDataPoints.begin(); it != fDataPoints.end(); ++it)
1209          {
1210             this->fSumw += (*it)->GetWeight();
1211             this->fSumw2 += pow((*it)->GetWeight(),2);
1212          }
1213          this->fEntries = fDataPoints.size();
1214 
1215          // create new splitting node
1216          SplitNode* pSplit = new SplitNode(fSplitAxis,fSplitValue,*this,*pNew,this->Parent());
1217 
1218          // link new splitting node
1219          this->GetParentPointer() = pSplit;
1220 
1221          // set splitting node as new parent of both terminal nodes
1222          this->Parent() = pSplit;
1223          pNew->Parent() = pSplit;
1224 
1225          // update boundaries
1226          this->UpdateBoundaries();
1227          pNew->UpdateBoundaries();
1228 
1229          // change splitting axis
1230          ++fSplitAxis;
1231          fSplitAxis = fSplitAxis % Dimension();
1232       }
1233 
1234 //______________________________________________________________________________
1235       template<class _DataPoint>
1236       typename KDTree<_DataPoint>::TerminalNode::data_it KDTree<_DataPoint>::TerminalNode::SplitEffectiveEntries()
1237       {
1238          //splits according to the number of effective entries
1239          //
1240          //returns an iterator pointing to the data point at which the vector should be split
1241          //
1242          //Note: - The vector containing the data points is partially ordered according to the
1243          //        coordinates of the current split axis at least until the position of cut.
1244 
1245          // function pointer for comparing data points
1246          typename KDTree<_DataPoint>::ComparePoints cComp;
1247          cComp.SetAxis(fSplitAxis);
1248 
1249          data_it first = fDataPoints.begin();
1250          data_it cut = first;
1251          data_it middle;
1252          UInt_t step = fDataPoints.size();
1253          Double_t fSumwTemp = 0;
1254          Double_t fSumw2Temp = 1e-7;
1255          Double_t fEffective = this->GetEffectiveEntries();
1256 
1257          // sort data points along split axis
1258          // find data point at which the cumulative effective entries reach half of the total effective entries
1259          while(((fSumwTemp * fSumwTemp)/fSumw2Temp < fEffective/2) && (step > 1))
1260          {
1261             middle = first + (++step /= 2);
1262             std::partial_sort(first,middle,fDataPoints.end(),cComp);
1263 
1264             while(((fSumwTemp * fSumwTemp)/fSumw2Temp < fEffective/2) && (cut != middle-1))
1265             {
1266                fSumwTemp += (*cut)->GetWeight();
1267                fSumw2Temp += pow((*cut)->GetWeight(),2);
1268                ++cut;
1269             }
1270             first = middle;
1271          }
1272 
1273          return cut;
1274       }
1275 
1276 //______________________________________________________________________________
1277       template<class _DataPoint>
1278       typename KDTree<_DataPoint>::TerminalNode::data_it KDTree<_DataPoint>::TerminalNode::SplitBinContent()
1279       {
1280          //splits according to the bin content
1281          //
1282          //returns an iterator pointing to the data point at which the vector should be split
1283          //
1284          //Note: - The vector containing the data points is partially ordered according to the
1285          //        coordinates of the current split axis at least until the position of cut.
1286 
1287          // function pointer for comparing data points
1288          typename KDTree<_DataPoint>::ComparePoints cComp;
1289          cComp.SetAxis(fSplitAxis);
1290 
1291          data_it first = fDataPoints.begin();
1292          data_it cut = first;
1293          data_it middle;
1294          UInt_t step = fDataPoints.size();
1295          Double_t fSumwTemp = 0;
1296          Double_t fBinContent = this->GetSumw();
1297 
1298          // sort data points along split axis
1299          // find data point at which the cumulative effective entries reach half of the total effective entries
1300          while((fSumwTemp < fBinContent/2) && (step > 1))
1301          {
1302             middle = first + (++step /= 2);
1303             std::partial_sort(first,middle,fDataPoints.end(),cComp);
1304 
1305             while((fSumwTemp < fBinContent/2) && (cut != middle-1))
1306             {
1307                fSumwTemp += (*cut)->GetWeight();
1308                ++cut;
1309             }
1310             first = middle;
1311          }
1312 
1313          return cut;
1314       }
1315 
1316 //______________________________________________________________________________
1317       template<class _DataPoint>
1318       void KDTree<_DataPoint>::TerminalNode::UpdateBoundaries()
1319       {
1320          //updates the boundaries of this bin and caches them
1321          //
1322          //Note: - In a high-dimensional space most of the nodes are bounded only on
1323          //        one side due to a split. One-sided intervals would result in an
1324          //        infinite volume of the bin which is not the desired behaviour.
1325          //        Therefore the following convention is used for determining the
1326          //        boundaries:
1327          //        If a node is not restricted along one axis on one/both side(s) due
1328          //        to a split, the corresponding upper/lower boundary is set to
1329          //        the minimum/maximum coordinate along this axis of all contained
1330          //        data points.
1331          //        This procedure maximises the density in the bins.
1332 
1333          const value_type fMAX = 0.4 * std::numeric_limits<value_type>::max();
1334          const value_type fMIN = -1.0 * fMAX;
1335 
1336          this->fBoundaries = std::vector<tBoundary>(Dimension(),std::make_pair(fMIN,fMAX));
1337 
1338          //walk back the tree and update bounds
1339          const BaseNode* pNode = this->Parent();
1340          const SplitNode* pSplit = 0;
1341          const Cut* pCut = 0;
1342          bool bLeft = this->IsLeftChild();
1343          while(!pNode->IsHeadNode())
1344          {
1345             pSplit = dynamic_cast<const SplitNode*>(pNode);
1346             assert(pSplit);
1347             pCut = pSplit->GetCut();
1348             // left subtree -> cut is upper bound
1349             if(bLeft)
1350                this->fBoundaries.at(pCut->GetAxis()).second = std::min(pCut->GetCutValue(),this->fBoundaries.at(pCut->GetAxis()).second);
1351             // right subtree -> cut is lower bound
1352             else
1353                this->fBoundaries.at(pCut->GetAxis()).first = std::max(pCut->GetCutValue(),this->fBoundaries.at(pCut->GetAxis()).first);
1354 
1355             bLeft = pNode->IsLeftChild();
1356             pNode = pNode->Parent();
1357          }
1358 
1359          // if there are some data points in this bucket, use their minimum/maximum values to define the open boundaries
1360          if(fDataPoints.size())
1361          {
1362             // loop over bounds and set unspecified values to minimum/maximum coordinate of all points in this bucket
1363             for(UInt_t dim = 0; dim < this->fBoundaries.size(); ++dim)
1364             {
1365                // check lower bound
1366                if(this->fBoundaries.at(dim).first < 0.8*fMIN)
1367                {
1368                   this->fBoundaries.at(dim).first = fMAX;
1369                   // look for smallest coordinate along axis 'dim'
1370                   for(typename std::vector<const _DataPoint*>::const_iterator it = fDataPoints.begin();
1371                       it != fDataPoints.end(); ++it)
1372                   {
1373                      if((*it)->GetCoordinate(dim) < this->fBoundaries.at(dim).first)
1374                         this->fBoundaries.at(dim).first = (*it)->GetCoordinate(dim);
1375                   }
1376                }
1377                // check upper bound
1378                if(this->fBoundaries.at(dim).second > 0.8*fMAX)
1379                {
1380                   this->fBoundaries.at(dim).second = fMIN;
1381                   // look for biggest coordinate along axis 'dim'
1382                   for(typename std::vector<const _DataPoint*>::const_iterator it = fDataPoints.begin();
1383                       it != fDataPoints.end(); ++it)
1384                   {
1385                      if((*it)->GetCoordinate(dim) > this->fBoundaries.at(dim).second)
1386                         this->fBoundaries.at(dim).second = (*it)->GetCoordinate(dim);
1387                   }
1388                }
1389             }
1390          }
1391       }
1392 
1393 //______________________________________________________________________________
1394       template<class _DataPoint>
1395       inline typename KDTree<_DataPoint>::iterator& KDTree<_DataPoint>::iterator::operator++()
1396       {
1397          //pre-increment operator
1398 
1399          fBin = Next();
1400          return *this;
1401       }
1402 
1403 //______________________________________________________________________________
1404       template<class _DataPoint>
1405       inline const typename KDTree<_DataPoint>::iterator& KDTree<_DataPoint>::iterator::operator++() const
1406       {
1407          //pre-increment operator
1408 
1409          fBin = Next();
1410          return *this;
1411       }
1412 
1413 //______________________________________________________________________________
1414       template<class _DataPoint>
1415       inline typename KDTree<_DataPoint>::iterator KDTree<_DataPoint>::iterator::operator++(int)
1416       {
1417          //post-increment operator
1418 
1419          iterator tmp(*this);
1420          fBin = Next();
1421          return tmp;
1422       }
1423 
1424 //______________________________________________________________________________
1425       template<class _DataPoint>
1426       inline const typename KDTree<_DataPoint>::iterator KDTree<_DataPoint>::iterator::operator++(int) const
1427       {
1428          //post-increment operator
1429 
1430          iterator tmp(*this);
1431          fBin = Next();
1432          return tmp;
1433       }
1434 
1435 //______________________________________________________________________________
1436       template<class _DataPoint>
1437       inline typename KDTree<_DataPoint>::iterator& KDTree<_DataPoint>::iterator::operator--()
1438       {
1439          //pre-decrement operator
1440 
1441          fBin = Previous();
1442          return *this;
1443       }
1444 
1445 //______________________________________________________________________________
1446       template<class _DataPoint>
1447       inline const typename KDTree<_DataPoint>::iterator& KDTree<_DataPoint>::iterator::operator--() const
1448       {
1449          //pre-decrement operator
1450 
1451          fBin = Previous();
1452          return *this;
1453       }
1454 
1455 //______________________________________________________________________________
1456       template<class _DataPoint>
1457       inline typename KDTree<_DataPoint>::iterator KDTree<_DataPoint>::iterator::operator--(int)
1458       {
1459          //post-decrement operator
1460 
1461          iterator tmp(*this);
1462          fBin = Previous();
1463          return tmp;
1464       }
1465 
1466 //______________________________________________________________________________
1467       template<class _DataPoint>
1468       inline const typename KDTree<_DataPoint>::iterator KDTree<_DataPoint>::iterator::operator--(int) const
1469       {
1470          //post-decrement operator
1471 
1472          iterator tmp(*this);
1473          fBin = Previous();
1474          return tmp;
1475       }
1476 
1477 //______________________________________________________________________________
1478       template<class _DataPoint>
1479       inline typename KDTree<_DataPoint>::iterator& KDTree<_DataPoint>::iterator::operator=(const typename KDTree<_DataPoint>::iterator& rhs)
1480       {
1481          //assignment operator
1482 
1483          fBin = rhs.fBin;
1484          return *this;
1485       }
1486 
1487 //______________________________________________________________________________
1488       template<class _DataPoint>
1489       typename KDTree<_DataPoint>::BinNode* KDTree<_DataPoint>::iterator::Next() const
1490       {
1491          //advance this iterator to the next bin
1492          //
1493          //Note: - Check for the end of all bins by comparing to End().
1494 
1495          BaseNode* pNode = fBin;
1496 
1497          while(!pNode->IsHeadNode())
1498          {
1499             if(pNode->IsLeftChild())
1500             {
1501                assert(pNode->Parent()->RightChild());
1502                pNode = pNode->Parent()->RightChild();
1503                while(pNode->LeftChild())
1504                   pNode = pNode->LeftChild();
1505 
1506                assert(dynamic_cast<BinNode*>(pNode));
1507                return (BinNode*)pNode;
1508             }
1509             else
1510                pNode = pNode->Parent();
1511          }
1512 
1513          return 0;
1514       }
1515 
1516 //______________________________________________________________________________
1517       template<class _DataPoint>
1518       typename KDTree<_DataPoint>::BinNode* KDTree<_DataPoint>::iterator::Previous() const
1519       {
1520          //decline this iterator to the previous bin
1521          //
1522          //Note: - Check for the end of all bins by comparing to End().
1523 
1524          BaseNode* pNode = fBin;
1525 
1526          while(!pNode->IsHeadNode())
1527          {
1528             if(pNode->Parent()->RightChild() == pNode)
1529             {
1530                assert(pNode->Parent()->LeftChild());
1531                pNode = pNode->Parent()->LeftChild();
1532                while(pNode->RightChild())
1533                   pNode = pNode->RightChild();
1534 
1535                assert(dynamic_cast<BinNode*>(pNode));
1536                return (BinNode*)pNode;
1537             }
1538             else
1539                pNode = pNode->Parent();
1540          }
1541 
1542          return 0;
1543       }
1544 
1545    }//namespace Math
1546 }//namespace ROOT
1547 
1548 #endif //KD_TREE_ICC