269template <
typename Index,
typename Value>
283 ,fBoundaries(nullptr)
291template <
typename Index,
typename Value>
305 ,fBoundaries(nullptr)
343template <
typename Index,
typename Value>
357 ,fBoundaries(nullptr)
372template <
typename Index,
typename Value>
375 if (fAxis)
delete [] fAxis;
376 if (fValue)
delete [] fValue;
377 if (fIndPoints)
delete [] fIndPoints;
378 if (fRange)
delete [] fRange;
379 if (fBoundaries)
delete [] fBoundaries;
383 for(
int idim=0; idim<fNDim; idim++)
delete [] fData[idim];
410template <
typename Index,
typename Value>
414 fNNodes = fNPoints/fBucketSize-1;
415 if (fNPoints%fBucketSize) fNNodes++;
416 fTotalNodes = fNNodes + fNPoints/fBucketSize + ((fNPoints%fBucketSize)?1:0);
419 for ( ;(fNNodes+1)>(1<<fRowT0);fRowT0++) {}
431 fRange =
new Value[2*fNDim];
432 fIndPoints=
new Index[fNPoints];
433 for (Index i=0; i<fNPoints; i++) fIndPoints[i] = i;
435 fValue =
new Value[fNNodes];
437 fCrossNode = (1<<(fRowT0+1))-1;
438 if (fCrossNode<fNNodes) fCrossNode = 2*fCrossNode+1;
441 Int_t over = (fNNodes+1)-(1<<fRowT0);
442 Int_t filled = ((1<<fRowT0)-over)*fBucketSize;
443 fOffset = fNPoints-filled;
454 Int_t nodeStack[128];
455 Int_t npointStack[128];
457 Int_t currentIndex = 0;
460 npointStack[0] = fNPoints;
463 while (currentIndex>=0){
465 Int_t npoints = npointStack[currentIndex];
466 if (npoints<=fBucketSize) {
470 Int_t crow = rowStack[currentIndex];
471 Int_t cpos = posStack[currentIndex];
472 Int_t cnode = nodeStack[currentIndex];
476 Int_t nbuckets0 = npoints/fBucketSize;
477 if (npoints%fBucketSize) nbuckets0++;
478 Int_t restRows = fRowT0-rowStack[currentIndex];
479 if (restRows<0) restRows =0;
480 for (;nbuckets0>(2<<restRows); restRows++) {}
481 Int_t nfull = 1<<restRows;
482 Int_t nrest = nbuckets0-nfull;
483 Int_t nleft =0, nright =0;
485 if (nrest>(nfull/2)){
486 nleft = nfull*fBucketSize;
487 nright = npoints-nleft;
489 nright = nfull*fBucketSize/2;
490 nleft = npoints-nright;
496 Value tempspread, min, max;
499 for (
Int_t idim=0; idim<fNDim; idim++){
501 Spread(npoints, array, fIndPoints+cpos, min, max);
502 tempspread = max - min;
503 if (maxspread < tempspread) {
504 maxspread=tempspread;
509 fRange[2*idim] = min; fRange[2*idim+1] = max;
511 array = fData[axspread];
512 KOrdStat(npoints, array, nleft, fIndPoints+cpos);
513 fAxis[cnode] = axspread;
514 fValue[cnode] = array[fIndPoints[cpos+nleft]];
518 npointStack[currentIndex] = nleft;
519 rowStack[currentIndex] = crow+1;
520 posStack[currentIndex] = cpos;
521 nodeStack[currentIndex] = cnode*2+1;
523 npointStack[currentIndex] = nright;
524 rowStack[currentIndex] = crow+1;
525 posStack[currentIndex] = cpos+nleft;
526 nodeStack[currentIndex] = (cnode*2)+2;
530 Info(
"Build()",
"%s",
Form(
"points %d left %d right %d", npoints, nleft, nright));
531 if (nleft<nright)
Warning(
"Build",
"Problem Left-Right");
532 if (nleft<0 || nright<0)
Warning(
"Build()",
"Problem Negative number");
542template <
typename Index,
typename Value>
547 Error(
"FindNearestNeighbors",
"Working arrays must be allocated by the user!");
551 dist[i]=std::numeric_limits<Value>::max();
554 MakeBoundariesExact();
555 UpdateNearestNeighbors(0, point,
kNN, ind, dist);
562template <
typename Index,
typename Value>
567 DistanceToNode(point, inode, min, max);
568 if (min > dist[
kNN-1]){
572 if (IsTerminal(inode)) {
574 Index
f1, l1, f2, l2;
575 GetNodePointsIndexes(inode,
f1, l1, f2, l2);
576 for (
Int_t ipoint=
f1; ipoint<=l1; ipoint++){
577 Double_t d = Distance(point, fIndPoints[ipoint]);
581 while(ishift<kNN && d>dist[ishift])
590 ind[ishift]=fIndPoints[ipoint];
595 if (point[fAxis[inode]]<fValue[inode]){
597 UpdateNearestNeighbors(GetLeft(inode), point,
kNN, ind, dist);
598 UpdateNearestNeighbors(GetRight(inode), point,
kNN, ind, dist);
600 UpdateNearestNeighbors(GetRight(inode), point,
kNN, ind, dist);
601 UpdateNearestNeighbors(GetLeft(inode), point,
kNN, ind, dist);
609template <
typename Index,
typename Value>
614 for (
Int_t idim=0; idim<fNDim; idim++){
615 dist+=(point[idim]-fData[idim][ind])*(point[idim]-fData[idim][ind]);
619 for (
Int_t idim=0; idim<fNDim; idim++){
620 dist+=
TMath::Abs(point[idim]-fData[idim][ind]);
634template <
typename Index,
typename Value>
637 Value *bound = GetBoundaryExact(inode);
643 for (
Int_t idim=0; idim<fNDimm; idim+=2){
644 dist1 = (point[idim/2]-bound[idim])*(point[idim/2]-bound[idim]);
645 dist2 = (point[idim/2]-bound[idim+1])*(point[idim/2]-bound[idim+1]);
647 if (point[idim/2]<bound[idim] || point[idim/2]>bound[idim+1])
648 min+= (dist1>dist2)? dist2 : dist1;
650 max+= (dist1>dist2)? dist1 : dist2;
655 for (
Int_t idim=0; idim<fNDimm; idim+=2){
656 dist1 =
TMath::Abs(point[idim/2]-bound[idim]);
657 dist2 =
TMath::Abs(point[idim/2]-bound[idim+1]);
659 min+= (dist1>dist2)? dist2 : dist1;
661 max+= (dist1>dist2)? dist1 : dist2;
671template <
typename Index,
typename Value>
674 Index stackNode[128], inode;
675 Int_t currentIndex =0;
677 while (currentIndex>=0){
678 inode = stackNode[currentIndex];
679 if (IsTerminal(inode))
return inode;
682 if (point[fAxis[inode]]<=fValue[inode]){
684 stackNode[currentIndex]=(inode<<1)+1;
686 if (point[fAxis[inode]]>=fValue[inode]){
688 stackNode[currentIndex]=(inode+1)<<1;
702template <
typename Index,
typename Value>
704 Int_t stackNode[128];
705 Int_t currentIndex =0;
709 while (currentIndex>=0){
711 Int_t inode = stackNode[currentIndex];
713 if (IsTerminal(inode)){
715 Int_t indexIP = (inode >= fCrossNode) ? (inode-fCrossNode)*fBucketSize : (inode-fNNodes)*fBucketSize+fOffset;
716 printf(
"terminal %d indexP %d\n", inode, indexIP);
717 for (
Int_t ibucket=0;ibucket<fBucketSize;ibucket++){
720 printf(
"ibucket %d index %d\n", ibucket, indexIP);
721 if (indexIP>=fNPoints)
continue;
722 Int_t index0 = fIndPoints[indexIP];
723 for (
Int_t idim=0;idim<fNDim;idim++)
if (fData[idim][index0]!=point[idim]) isOK =
kFALSE;
724 if (isOK)
index = index0;
729 if (point[fAxis[inode]]<=fValue[inode]){
731 stackNode[currentIndex]=(inode*2)+1;
733 if (point[fAxis[inode]]>=fValue[inode]){
735 stackNode[currentIndex]=(inode*2)+2;
748template <
typename Index,
typename Value>
751 MakeBoundariesExact();
752 UpdateRange(0, point, range, res);
758template <
typename Index,
typename Value>
762 DistanceToNode(point, inode, min, max);
767 if (max<range && max>0) {
770 Index
f1, l1, f2, l2;
771 GetNodePointsIndexes(inode,
f1, l1, f2, l2);
773 for (
Int_t ipoint=
f1; ipoint<=l1; ipoint++){
774 res.push_back(fIndPoints[ipoint]);
776 for (
Int_t ipoint=f2; ipoint<=l2; ipoint++){
777 res.push_back(fIndPoints[ipoint]);
783 if (IsTerminal(inode)){
785 Index
f1, l1, f2, l2;
787 GetNodePointsIndexes(inode,
f1, l1, f2, l2);
788 for (
Int_t ipoint=
f1; ipoint<=l1; ipoint++){
789 d = Distance(point, fIndPoints[ipoint]);
791 res.push_back(fIndPoints[ipoint]);
796 if (point[fAxis[inode]]<=fValue[inode]){
798 UpdateRange(GetLeft(inode),point, range, res);
799 UpdateRange(GetRight(inode),point, range, res);
801 UpdateRange(GetLeft(inode),point, range, res);
802 UpdateRange(GetRight(inode),point, range, res);
811template <
typename Index,
typename Value>
814 if (!IsTerminal(node)){
815 printf(
"GetPointsIndexes() only for terminal nodes, use GetNodePointsIndexes() instead\n");
818 Int_t offset = (node >= fCrossNode) ? (node-fCrossNode)*fBucketSize : fOffset+(node-fNNodes)*fBucketSize;
819 return &fIndPoints[
offset];
840template <
typename Index,
typename Value>
844 if (IsTerminal(node)){
846 Index
offset = (node >= fCrossNode) ? (node-fCrossNode)*fBucketSize : fOffset+(node-fNNodes)*fBucketSize;
848 last1 =
offset + GetNPointsNode(node)-1;
854 Index firsttermnode = fNNodes;
857 Index
f1, l1, f2, l2;
859 while (ileft<firsttermnode)
860 ileft = GetLeft(ileft);
862 while (iright<firsttermnode)
863 iright = GetRight(iright);
870 GetNodePointsIndexes(firsttermnode,
f1, l1, f2, l2);
872 GetNodePointsIndexes(iright,
f1, l1, f2, l2);
874 GetNodePointsIndexes(ileft,
f1, l1, f2, l2);
876 GetNodePointsIndexes(fTotalNodes-1,
f1, l1, f2, l2);
880 GetNodePointsIndexes(ileft,
f1, l1, f2, l2);
882 GetNodePointsIndexes(iright,
f1, l1, f2, l2);
894template <
typename Index,
typename Value>
897 if (IsTerminal(inode)){
899 if (inode!=fTotalNodes-1)
return fBucketSize;
901 if (fOffset%fBucketSize==0)
return fBucketSize;
902 else return fOffset%fBucketSize;
907 GetNodePointsIndexes(inode,
f1, l1, f2, l2);
917template <
typename Index,
typename Value>
942template <
typename Index,
typename Value>
945 if (fAxis || fValue) {
946 Error(
"SetData",
"The tree has already been built, no updates possible");
951 fData =
new Value*[fNDim];
962template <
typename Index,
typename Value>
968 for (i=0; i<ntotal; i++){
979template <
typename Index,
typename Value>
982 Index i, ir, j,
l, mid;
1011 do i++;
while (
a[
index[i]]<
a[arr]);
1012 do j--;
while (
a[
index[j]]>
a[arr]);
1018 if (j>=rk) ir = j-1;
1033template <
typename Index,
typename Value>
1037 if(range) memcpy(fRange, range, fNDimm*
sizeof(
Value));
1039 Int_t totNodes = fNNodes + fNPoints/fBucketSize + ((fNPoints%fBucketSize)?1:0);
1040 fBoundaries =
new Value[totNodes*fNDimm];
1045 Value *tbounds =
nullptr, *cbounds =
nullptr;
1047 for(
int inode=fNNodes-1; inode>=0; inode--){
1048 tbounds = &fBoundaries[inode*fNDimm];
1049 memcpy(tbounds, fRange, fNDimm*
sizeof(
Value));
1053 if(IsTerminal(cn)) CookBoundaries(inode,
kTRUE);
1054 cbounds = &fBoundaries[fNDimm*cn];
1055 for(
int idim=0; idim<fNDim; idim++) tbounds[idim<<1] = cbounds[idim<<1];
1059 if(IsTerminal(cn)) CookBoundaries(inode,
kFALSE);
1060 cbounds = &fBoundaries[fNDimm*cn];
1061 for(
int idim=0; idim<fNDim; idim++) tbounds[(idim<<1)+1] = cbounds[(idim<<1)+1];
1068template <
typename Index,
typename Value>
1076 memcpy(tbounds, fRange, fNDimm*
sizeof(
Value));
1078 memset(flag,
kFALSE, fNDimm);
1083 while(pn >= 0 && nvals < fNDimm){
1085 index = (fAxis[pn]<<1)+1;
1087 tbounds[
index] = fValue[pn];
1092 index = fAxis[pn]<<1;
1094 tbounds[
index] = fValue[pn];
1113template <
typename Index,
typename Value>
1123 fBoundaries =
new Value[fTotalNodes*fNDimm];
1126 for (Index inode=fNNodes; inode<fTotalNodes; inode++){
1128 for (Index idim=0; idim<fNDim; idim++){
1129 min[idim]= std::numeric_limits<Value>::max();
1130 max[idim]=-std::numeric_limits<Value>::max();
1132 Index *
points = GetPointsIndexes(inode);
1133 Index npoints = GetNPointsNode(inode);
1135 for (Index ipoint=0; ipoint<npoints; ipoint++){
1136 for (Index idim=0; idim<fNDim; idim++){
1137 if (fData[idim][
points[ipoint]]<min[idim])
1138 min[idim]=fData[idim][
points[ipoint]];
1139 if (fData[idim][
points[ipoint]]>max[idim])
1140 max[idim]=fData[idim][
points[ipoint]];
1143 for (Index idim=0; idim<fNDimm; idim+=2){
1144 fBoundaries[inode*fNDimm + idim]=min[idim/2];
1145 fBoundaries[inode*fNDimm + idim+1]=max[idim/2];
1153 for (Index inode=fNNodes-1; inode>=0; inode--){
1155 left = GetLeft(inode)*fNDimm;
1156 right = GetRight(inode)*fNDimm;
1157 for (Index idim=0; idim<fNDimm; idim+=2){
1159 fBoundaries[inode*fNDimm+idim]=
TMath::Min(fBoundaries[left+idim], fBoundaries[right+idim]);
1161 fBoundaries[inode*fNDimm+idim+1]=
TMath::Max(fBoundaries[left+idim+1], fBoundaries[right+idim+1]);
1172template <
typename Index,
typename Value>
1175 for (;inode<fNNodes;){
1176 if (
TMath::Abs(point[fAxis[inode]] - fValue[inode])<delta[fAxis[inode]])
break;
1177 inode = (point[fAxis[inode]] < fValue[inode]) ? (inode*2)+1: (inode*2)+2;
1184template <
typename Index,
typename Value>
1187 if(!fBoundaries) MakeBoundaries();
1195template <
typename Index,
typename Value>
1198 if(!fBoundaries) MakeBoundariesExact();
1205template <
typename Index,
typename Value>
1208 if(!fBoundaries) MakeBoundaries();
1209 return &fBoundaries[node*2*fNDim];
1215template <
typename Index,
typename Value>
1218 if(!fBoundaries) MakeBoundariesExact();
1219 return &fBoundaries[node*2*fNDim];
1231 data[0] = &data0[0];
1232 data[1] = &data0[npoints];
1233 for (
Int_t i=0;i<npoints;i++) {
#define templateClassImp(name)
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t points
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
TKDTreeIF * TKDTreeTestBuild()
TKDTree< Int_t, Float_t > TKDTreeIF
R__EXTERN TRandom * gRandom
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Class implementing a kd-tree.
void FindPoint(Value *point, Index &index, Int_t &iter)
find the index of point works only if we keep fData pointers
void SetData(Index npoints, Index ndim, UInt_t bsize, Value **data)
Set the data array. See the constructor function comments for details.
~TKDTree() override
Destructor By default, the original data is not owned by kd-tree and is not deleted with it.
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...
Value * GetBoundaryExact(const Int_t node)
Get a boundary.
void FindBNodeA(Value *point, Value *delta, Int_t &inode)
find the smallest node covering the full range - start
void UpdateRange(Index inode, Value *point, Value range, std::vector< Index > &res)
Internal recursive function with the implementation of range searches.
Index FindNode(const Value *point) const
returns the index of the terminal node to which point belongs (index in the fAxis,...
Value KOrdStat(Index ntotal, Value *a, Index k, Index *index) const
copy of the TMath::KOrdStat because I need an Index work array
Value * GetBoundariesExact()
Get the boundaries.
void MakeBoundariesExact()
Build boundaries for each node.
void CookBoundaries(const Int_t node, Bool_t left)
define index of this terminal node
void MakeBoundaries(Value *range=nullptr)
Build boundaries for each node.
void UpdateNearestNeighbors(Index inode, const Value *point, Int_t kNN, Index *ind, Value *dist)
Update the nearest neighbors values by examining the node inode.
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 ...
Index * GetPointsIndexes(Int_t node) const
return the indices of the points in that terminal node for all the nodes except last,...
void Spread(Index ntotal, Value *a, Index *index, Value &min, Value &max) const
Calculate spread of the array a.
void Build()
Build the kd-tree.
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.
TKDTree()
Default constructor. Nothing is built.
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...
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...
Value * GetBoundaries()
Get the boundaries.
Value * GetBoundary(const Int_t node)
Get a boundary.
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,...
kNN::Event describes point in input variable vector-space, with additional functionality like distanc...
Mother of all ROOT objects.
Double_t Rndm() override
Machine independent random number generator.
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Double_t Sqrt(Double_t x)
Returns the square root of x.
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
static uint64_t sum(uint64_t i)