293 template <
typename Index,
typename Value>
345 template <
typename Index,
typename Value>
374 template <
typename Index,
typename Value>
377 if (fAxis)
delete [] fAxis;
379 if (fIndPoints)
delete [] fIndPoints;
380 if (fRange)
delete [] fRange;
381 if (fBoundaries)
delete [] fBoundaries;
385 for(
int idim=0; idim<fNDim; idim++)
delete [] fData[idim];
412 template <
typename Index,
typename Value>
416 fNNodes = fNPoints/fBucketSize-1;
417 if (fNPoints%fBucketSize) fNNodes++;
418 fTotalNodes = fNNodes + fNPoints/fBucketSize + ((fNPoints%fBucketSize)?1:0);
421 for ( ;(fNNodes+1)>(1<<fRowT0);fRowT0++) {}
433 fRange =
new Value[2*fNDim];
434 fIndPoints=
new Index[fNPoints];
435 for (
Index i=0; i<fNPoints; i++) fIndPoints[i] = i;
439 fCrossNode = (1<<(fRowT0+1))-1;
440 if (fCrossNode<fNNodes) fCrossNode = 2*fCrossNode+1;
443 Int_t over = (fNNodes+1)-(1<<fRowT0);
444 Int_t filled = ((1<<fRowT0)-over)*fBucketSize;
445 fOffset = fNPoints-filled;
456 Int_t nodeStack[128];
457 Int_t npointStack[128];
459 Int_t currentIndex = 0;
463 npointStack[0] = fNPoints;
466 Int_t nbucketsall =0;
467 while (currentIndex>=0){
470 Int_t npoints = npointStack[currentIndex];
471 if (npoints<=fBucketSize) {
477 Int_t crow = rowStack[currentIndex];
478 Int_t cpos = posStack[currentIndex];
479 Int_t cnode = nodeStack[currentIndex];
483 Int_t nbuckets0 = npoints/fBucketSize;
484 if (npoints%fBucketSize) nbuckets0++;
485 Int_t restRows = fRowT0-rowStack[currentIndex];
486 if (restRows<0) restRows =0;
487 for (;nbuckets0>(2<<restRows); restRows++) {}
488 Int_t nfull = 1<<restRows;
489 Int_t nrest = nbuckets0-nfull;
490 Int_t nleft =0, nright =0;
492 if (nrest>(nfull/2)){
493 nleft = nfull*fBucketSize;
494 nright = npoints-nleft;
496 nright = nfull*fBucketSize/2;
497 nleft = npoints-nright;
506 for (
Int_t idim=0; idim<fNDim; idim++){
508 Spread(npoints, array, fIndPoints+cpos, min, max);
509 tempspread = max -
min;
510 if (maxspread < tempspread) {
511 maxspread=tempspread;
516 fRange[2*idim] =
min; fRange[2*idim+1] =
max;
518 array = fData[axspread];
519 KOrdStat(npoints, array, nleft, fIndPoints+cpos);
520 fAxis[cnode] = axspread;
521 fValue[cnode] = array[fIndPoints[cpos+nleft]];
525 npointStack[currentIndex] = nleft;
526 rowStack[currentIndex] = crow+1;
527 posStack[currentIndex] = cpos;
528 nodeStack[currentIndex] = cnode*2+1;
530 npointStack[currentIndex] = nright;
531 rowStack[currentIndex] = crow+1;
532 posStack[currentIndex] = cpos+nleft;
533 nodeStack[currentIndex] = (cnode*2)+2;
537 Info(
"Build()",
"%s",
Form(
"points %d left %d right %d", npoints, nleft, nright));
538 if (nleft<nright)
Warning(
"Build",
"Problem Left-Right");
539 if (nleft<0 || nright<0)
Warning(
"Build()",
"Problem Negative number");
549 template <
typename Index,
typename Value>
554 Error(
"FindNearestNeighbors",
"Working arrays must be allocated by the user!");
557 for (
Int_t i=0; i<kNN; i++){
561 MakeBoundariesExact();
562 UpdateNearestNeighbors(0, point, kNN, ind, dist);
569 template <
typename Index,
typename Value>
574 DistanceToNode(point, inode, min, max);
575 if (min > dist[kNN-1]){
579 if (IsTerminal(inode)) {
582 GetNodePointsIndexes(inode, f1, l1, f2, l2);
583 for (
Int_t ipoint=f1; ipoint<=
l1; ipoint++){
588 while(ishift<kNN && d>dist[ishift])
592 for (
Int_t i=kNN-1; i>ishift; i--){
597 ind[ishift]=fIndPoints[ipoint];
602 if (point[fAxis[inode]]<
fValue[inode]){
604 UpdateNearestNeighbors(GetLeft(inode), point, kNN, ind, dist);
605 UpdateNearestNeighbors(GetRight(inode), point, kNN, ind, dist);
607 UpdateNearestNeighbors(GetRight(inode), point, kNN, ind, dist);
608 UpdateNearestNeighbors(GetLeft(inode), point, kNN, ind, dist);
616 template <
typename Index,
typename Value>
621 for (
Int_t idim=0; idim<fNDim; idim++){
622 dist+=(point[idim]-fData[idim][ind])*(point[idim]-fData[idim][ind]);
626 for (
Int_t idim=0; idim<fNDim; idim++){
627 dist+=
TMath::Abs(point[idim]-fData[idim][ind]);
641 template <
typename Index,
typename Value>
644 Value *bound = GetBoundaryExact(inode);
650 for (
Int_t idim=0; idim<fNDimm; idim+=2){
651 dist1 = (point[idim/2]-bound[idim])*(point[idim/2]-bound[idim]);
652 dist2 = (point[idim/2]-bound[idim+1])*(point[idim/2]-bound[idim+1]);
654 if (point[idim/2]<bound[idim] || point[idim/2]>bound[idim+1])
655 min+= (dist1>dist2)? dist2 : dist1;
657 max+= (dist1>dist2)? dist1 : dist2;
662 for (
Int_t idim=0; idim<fNDimm; idim+=2){
663 dist1 =
TMath::Abs(point[idim/2]-bound[idim]);
664 dist2 =
TMath::Abs(point[idim/2]-bound[idim+1]);
666 min+= (dist1>dist2)? dist2 : dist1;
668 max+= (dist1>dist2)? dist1 : dist2;
678 template <
typename Index,
typename Value>
681 Index stackNode[128], inode;
682 Int_t currentIndex =0;
684 while (currentIndex>=0){
685 inode = stackNode[currentIndex];
686 if (IsTerminal(inode))
return inode;
689 if (point[fAxis[inode]]<=
fValue[inode]){
691 stackNode[currentIndex]=(inode<<1)+1;
693 if (point[fAxis[inode]]>=
fValue[inode]){
695 stackNode[currentIndex]=(inode+1)<<1;
709 template <
typename Index,
typename Value>
711 Int_t stackNode[128];
712 Int_t currentIndex =0;
716 while (currentIndex>=0){
718 Int_t inode = stackNode[currentIndex];
720 if (IsTerminal(inode)){
722 Int_t indexIP = (inode >= fCrossNode) ? (inode-fCrossNode)*fBucketSize : (inode-fNNodes)*fBucketSize+fOffset;
723 printf(
"terminal %d indexP %d\n", inode, indexIP);
724 for (
Int_t ibucket=0;ibucket<fBucketSize;ibucket++){
727 printf(
"ibucket %d index %d\n", ibucket, indexIP);
728 if (indexIP>=fNPoints)
continue;
729 Int_t index0 = fIndPoints[indexIP];
730 for (
Int_t idim=0;idim<fNDim;idim++)
if (fData[idim][index0]!=point[idim]) isOK =
kFALSE;
731 if (isOK) index = index0;
736 if (point[fAxis[inode]]<=
fValue[inode]){
738 stackNode[currentIndex]=(inode*2)+1;
740 if (point[fAxis[inode]]>=
fValue[inode]){
742 stackNode[currentIndex]=(inode*2)+2;
755 template <
typename Index,
typename Value>
758 MakeBoundariesExact();
759 UpdateRange(0, point, range, res);
765 template <
typename Index,
typename Value>
769 DistanceToNode(point, inode, min, max);
774 if (max<range && max>0) {
778 GetNodePointsIndexes(inode, f1, l1, f2, l2);
780 for (
Int_t ipoint=f1; ipoint<=
l1; ipoint++){
781 res.push_back(fIndPoints[ipoint]);
783 for (
Int_t ipoint=f2; ipoint<=l2; ipoint++){
784 res.push_back(fIndPoints[ipoint]);
790 if (IsTerminal(inode)){
794 GetNodePointsIndexes(inode, f1, l1, f2, l2);
795 for (
Int_t ipoint=f1; ipoint<=
l1; ipoint++){
796 d =
Distance(point, fIndPoints[ipoint]);
798 res.push_back(fIndPoints[ipoint]);
803 if (point[fAxis[inode]]<=
fValue[inode]){
805 UpdateRange(GetLeft(inode),point, range, res);
806 UpdateRange(GetRight(inode),point, range, res);
808 UpdateRange(GetLeft(inode),point, range, res);
809 UpdateRange(GetRight(inode),point, range, res);
818 template <
typename Index,
typename Value>
821 if (!IsTerminal(node)){
822 printf(
"GetPointsIndexes() only for terminal nodes, use GetNodePointsIndexes() instead\n");
825 Int_t offset = (node >= fCrossNode) ? (node-fCrossNode)*fBucketSize : fOffset+(node-fNNodes)*fBucketSize;
826 return &fIndPoints[
offset];
847 template <
typename Index,
typename Value>
851 if (IsTerminal(node)){
853 Index offset = (node >= fCrossNode) ? (node-fCrossNode)*fBucketSize : fOffset+(node-fNNodes)*fBucketSize;
855 last1 = offset + GetNPointsNode(node)-1;
861 Index firsttermnode = fNNodes;
866 while (ileft<firsttermnode)
867 ileft = GetLeft(ileft);
869 while (iright<firsttermnode)
870 iright = GetRight(iright);
877 GetNodePointsIndexes(firsttermnode, f1, l1, f2, l2);
879 GetNodePointsIndexes(iright, f1, l1, f2, l2);
881 GetNodePointsIndexes(ileft, f1, l1, f2, l2);
883 GetNodePointsIndexes(fTotalNodes-1, f1, l1, f2, l2);
887 GetNodePointsIndexes(ileft, f1, l1, f2, l2);
889 GetNodePointsIndexes(iright, f1, l1, f2, l2);
901 template <
typename Index,
typename Value>
904 if (IsTerminal(inode)){
906 if (inode!=fTotalNodes-1)
return fBucketSize;
908 if (fOffset%fBucketSize==0)
return fBucketSize;
909 else return fOffset%fBucketSize;
914 GetNodePointsIndexes(inode, f1, l1, f2, l2);
924 template <
typename Index,
typename Value>
949 template <
typename Index,
typename Value>
953 Error(
"SetData",
"The tree has already been built, no updates possible");
958 fData =
new Value*[fNDim];
969 template <
typename Index,
typename Value>
975 for (i=0; i<ntotal; i++){
976 if (a[index[i]]<min) min = a[index[i]];
977 if (a[index[i]]>max) max = a[index[i]];
986 template <
typename Index,
typename Value>
998 if (ir == l+1 && a[index[ir]]<a[index[l]])
999 {temp = index[
l]; index[
l]=index[ir]; index[ir]=temp;}
1000 Value tmp = a[index[rk]];
1004 {temp = index[mid]; index[mid]=index[l+1]; index[l+1]=temp;}
1005 if (a[index[l]]>a[index[ir]])
1006 {temp = index[
l]; index[
l]=index[ir]; index[ir]=temp;}
1008 if (a[index[l+1]]>a[index[ir]])
1009 {temp=index[l+1]; index[l+1]=index[ir]; index[ir]=temp;}
1011 if (a[index[l]]>a[index[l+1]])
1012 {temp = index[
l]; index[
l]=index[l+1]; index[l+1]=temp;}
1018 do i++;
while (a[index[i]]<a[arr]);
1019 do j--;
while (a[index[j]]>a[arr]);
1021 {temp=index[i]; index[i]=index[j]; index[j]=temp;}
1023 index[l+1]=index[j];
1025 if (j>=rk) ir = j-1;
1040 template <
typename Index,
typename Value>
1044 if(range) memcpy(fRange, range, fNDimm*
sizeof(
Value));
1046 Int_t totNodes = fNNodes + fNPoints/fBucketSize + ((fNPoints%fBucketSize)?1:0);
1047 fBoundaries =
new Value[totNodes*fNDimm];
1052 Value *tbounds = 0x0, *cbounds = 0x0;
1054 for(
int inode=fNNodes-1; inode>=0; inode--){
1055 tbounds = &fBoundaries[inode*fNDimm];
1056 memcpy(tbounds, fRange, fNDimm*
sizeof(
Value));
1060 if(IsTerminal(cn)) CookBoundaries(inode,
kTRUE);
1061 cbounds = &fBoundaries[fNDimm*cn];
1062 for(
int idim=0; idim<fNDim; idim++) tbounds[idim<<1] = cbounds[idim<<1];
1066 if(IsTerminal(cn)) CookBoundaries(inode,
kFALSE);
1067 cbounds = &fBoundaries[fNDimm*cn];
1068 for(
int idim=0; idim<fNDim; idim++) tbounds[(idim<<1)+1] = cbounds[(idim<<1)+1];
1075 template <
typename Index,
typename Value>
1078 Int_t index = (node<<1) + (LEFT ? 1 : 2);
1082 Value *tbounds = &fBoundaries[fNDimm*index];
1083 memcpy(tbounds, fRange, fNDimm*
sizeof(
Value));
1085 memset(flag,
kFALSE, fNDimm);
1090 while(pn >= 0 && nvals < fNDimm){
1092 index = (fAxis[pn]<<1)+1;
1094 tbounds[index] =
fValue[pn];
1095 flag[index] =
kTRUE;
1099 index = fAxis[pn]<<1;
1101 tbounds[index] =
fValue[pn];
1102 flag[index] =
kTRUE;
1120 template <
typename Index,
typename Value>
1130 fBoundaries =
new Value[fTotalNodes*fNDimm];
1133 for (
Index inode=fNNodes; inode<fTotalNodes; inode++){
1135 for (
Index idim=0; idim<fNDim; idim++){
1140 Index npoints = GetNPointsNode(inode);
1142 for (
Index ipoint=0; ipoint<npoints; ipoint++){
1143 for (
Index idim=0; idim<fNDim; idim++){
1144 if (fData[idim][points[ipoint]]<min[idim])
1145 min[idim]=fData[idim][points[ipoint]];
1146 if (fData[idim][points[ipoint]]>max[idim])
1147 max[idim]=fData[idim][points[ipoint]];
1150 for (
Index idim=0; idim<fNDimm; idim+=2){
1151 fBoundaries[inode*fNDimm + idim]=min[idim/2];
1152 fBoundaries[inode*fNDimm + idim+1]=max[idim/2];
1160 for (
Index inode=fNNodes-1; inode>=0; inode--){
1162 left = GetLeft(inode)*fNDimm;
1163 right = GetRight(inode)*fNDimm;
1164 for (
Index idim=0; idim<fNDimm; idim+=2){
1166 fBoundaries[inode*fNDimm+idim]=
TMath::Min(fBoundaries[left+idim], fBoundaries[right+idim]);
1168 fBoundaries[inode*fNDimm+idim+1]=
TMath::Max(fBoundaries[left+idim+1], fBoundaries[right+idim+1]);
1179 template <
typename Index,
typename Value>
1182 for (;inode<fNNodes;){
1183 if (
TMath::Abs(point[fAxis[inode]] -
fValue[inode])<delta[fAxis[inode]])
break;
1184 inode = (point[fAxis[inode]] <
fValue[inode]) ? (inode*2)+1: (inode*2)+2;
1191 template <
typename Index,
typename Value>
1194 if(!fBoundaries) MakeBoundaries();
1202 template <
typename Index,
typename Value>
1205 if(!fBoundaries) MakeBoundariesExact();
1212 template <
typename Index,
typename Value>
1215 if(!fBoundaries) MakeBoundaries();
1216 return &fBoundaries[node*2*fNDim];
1222 template <
typename Index,
typename Value>
1225 if(!fBoundaries) MakeBoundariesExact();
1226 return &fBoundaries[node*2*fNDim];
1238 data[0] = &data0[0];
1239 data[1] = &data0[npoints];
1240 for (
Int_t i=0;i<npoints;i++) {
void Spread(Index ntotal, Value *a, Index *index, Value &min, Value &max) const
Calculate spread of the array a.
double dist(Rotation3D const &r1, Rotation3D const &r2)
static Vc_ALWAYS_INLINE int_v min(const int_v &x, const int_v &y)
void SetData(Index npoints, Index ndim, UInt_t bsize, Value **data)
Set the data array. See the constructor function comments for details.
Small helper to encapsulate whether to return the value pointed to by the iterator or its address...
TKDTree< Int_t, Float_t > TKDTreeIF
virtual Double_t Rndm(Int_t i=0)
Machine independent random number generator.
void FindBNodeA(Value *point, Value *delta, Int_t &inode)
find the smallest node covering the full range - start
void FindInRange(Value *point, Value range, std::vector< Index > &res)
Find all points in the sphere of a given radius "range" around the given point 1st argument - the poi...
Short_t Min(Short_t a, Short_t b)
void MakeBoundariesExact()
Build boundaries for each node.
void Build()
Build the kd-tree.
#define templateClassImp(name)
void FindPoint(Value *point, Index &index, Int_t &iter)
find the index of point works only if we keep fData pointers
TLine l1(2.5, 4.5, 15.5, 4.5)
std::map< std::string, std::string >::const_iterator iter
void Info(const char *location, const char *msgfmt,...)
TKDTreeIF * TKDTreeTestBuild(const Int_t npoints, const Int_t bsize)
Example function to.
void GetNodePointsIndexes(Int_t node, Int_t &first1, Int_t &last1, Int_t &first2, Int_t &last2) const
Return the indices of points in that node Indices are returned as the first and last value of the par...
void Error(const char *location, const char *msgfmt,...)
Value KOrdStat(Index ntotal, Value *a, Index k, Index *index) const
copy of the TMath::KOrdStat because I need an Index work array
void UpdateNearestNeighbors(Index inode, const Value *point, Int_t kNN, Index *ind, Value *dist)
Update the nearest neighbors values by examining the node inode.
~TKDTree()
Destructor By default, the original data is not owned by kd-tree and is not deleted with it...
Index GetNPointsNode(Int_t node) const
Get number of points in this node for all the terminal nodes except last, the size is fBucketSize for...
char * Form(const char *fmt,...)
void FindNearestNeighbors(const Value *point, Int_t k, Index *ind, Value *dist)
Find kNN nearest neighbors to the point in the first argument Returns 1 on success, 0 on failure Arrays ind and dist are provided by the user and are assumed to be at least kNN elements long.
void CookBoundaries(const Int_t node, Bool_t left)
define index of this terminal node
void Warning(const char *location, const char *msgfmt,...)
R__EXTERN TRandom * gRandom
void DistanceToNode(const Value *point, Index inode, Value &min, Value &max, Int_t type=2)
Find the minimal and maximal distance from a given point to a given node.
void MakeBoundaries(Value *range=0x0)
Build boundaries for each node.
RooCmdArg Index(RooCategory &icat)
Value * GetBoundariesExact()
Get the boundaries.
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
Double_t Distance(const Value *point, Index ind, Int_t type=2) const
Find the distance between point of the first argument and the point at index value ind Type argument ...
static Vc_ALWAYS_INLINE int_v max(const int_v &x, const int_v &y)
Mother of all ROOT objects.
Element KOrdStat(Size n, const Element *a, Size k, Size *work=0)
void UpdateRange(Index inode, Value *point, Value range, std::vector< Index > &res)
Internal recursive function with the implementation of range searches.
Short_t Max(Short_t a, Short_t b)
AxisAngle::Scalar Distance(const AxisAngle &r1, const R &r2)
Distance between two rotations.
Value * GetBoundaries()
Get the boundaries.
Double_t Sqrt(Double_t x)
Index * GetPointsIndexes(Int_t node) const
return the indices of the points in that terminal node for all the nodes except last, the size is fBucketSize for the last node it's fOffsetfBucketSize
Value * GetBoundaryExact(const Int_t node)
Get a boundary.
Value * GetBoundary(const Int_t node)
Get a boundary.
Index FindNode(const Value *point) const
returns the index of the terminal node to which point belongs (index in the fAxis, fValue, etc arrays) returns -1 in case of failure