00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TKDTree.h"
00013 #include "TRandom.h"
00014
00015 #include "TString.h"
00016 #include <string.h>
00017 #include <limits>
00018
00019 #ifndef R__ALPHA
00020 templateClassImp(TKDTree)
00021 #endif
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 template <typename Index, typename Value>
00248 TKDTree<Index, Value>::TKDTree() :
00249 TObject()
00250 ,fDataOwner(kFALSE)
00251 ,fNNodes(0)
00252 ,fTotalNodes(0)
00253 ,fNDim(0)
00254 ,fNDimm(0)
00255 ,fNPoints(0)
00256 ,fBucketSize(0)
00257 ,fAxis(0x0)
00258 ,fValue(0x0)
00259 ,fRange(0x0)
00260 ,fData(0x0)
00261 ,fBoundaries(0x0)
00262 ,fIndPoints(0x0)
00263 ,fRowT0(0)
00264 ,fCrossNode(0)
00265 ,fOffset(0)
00266 {
00267
00268 }
00269
00270 template <typename Index, typename Value>
00271 TKDTree<Index, Value>::TKDTree(Index npoints, Index ndim, UInt_t bsize) :
00272 TObject()
00273 ,fDataOwner(0)
00274 ,fNNodes(0)
00275 ,fTotalNodes(0)
00276 ,fNDim(ndim)
00277 ,fNDimm(2*ndim)
00278 ,fNPoints(npoints)
00279 ,fBucketSize(bsize)
00280 ,fAxis(0x0)
00281 ,fValue(0x0)
00282 ,fRange(0x0)
00283 ,fData(0x0)
00284 ,fBoundaries(0x0)
00285 ,fIndPoints(0x0)
00286 ,fRowT0(0)
00287 ,fCrossNode(0)
00288 ,fOffset(0)
00289 {
00290
00291
00292
00293
00294
00295
00296 }
00297
00298
00299 template <typename Index, typename Value>
00300 TKDTree<Index, Value>::TKDTree(Index npoints, Index ndim, UInt_t bsize, Value **data) :
00301 TObject()
00302 ,fDataOwner(0)
00303 ,fNNodes(0)
00304 ,fTotalNodes(0)
00305 ,fNDim(ndim)
00306 ,fNDimm(2*ndim)
00307 ,fNPoints(npoints)
00308 ,fBucketSize(bsize)
00309 ,fAxis(0x0)
00310 ,fValue(0x0)
00311 ,fRange(0x0)
00312 ,fData(data)
00313 ,fBoundaries(0x0)
00314 ,fIndPoints(0x0)
00315 ,fRowT0(0)
00316 ,fCrossNode(0)
00317 ,fOffset(0)
00318 {
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 }
00345
00346
00347 template <typename Index, typename Value>
00348 TKDTree<Index, Value>::~TKDTree()
00349 {
00350
00351
00352
00353
00354 if (fAxis) delete [] fAxis;
00355 if (fValue) delete [] fValue;
00356 if (fIndPoints) delete [] fIndPoints;
00357 if (fRange) delete [] fRange;
00358 if (fBoundaries) delete [] fBoundaries;
00359 if (fData) {
00360 if (fDataOwner==1){
00361
00362 for(int idim=0; idim<fNDim; idim++) delete [] fData[idim];
00363 }
00364 if (fDataOwner>0) {
00365
00366 delete [] fData;
00367 }
00368 }
00369
00370
00371
00372
00373 }
00374
00375
00376
00377 template <typename Index, typename Value>
00378 void TKDTree<Index, Value>::Build()
00379 {
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 fNNodes = fNPoints/fBucketSize-1;
00394 if (fNPoints%fBucketSize) fNNodes++;
00395 fTotalNodes = fNNodes + fNPoints/fBucketSize + ((fNPoints%fBucketSize)?1:0);
00396
00397 fRowT0=0;
00398 for ( ;(fNNodes+1)>(1<<fRowT0);fRowT0++) {}
00399 fRowT0-=1;
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 fRange = new Value[2*fNDim];
00411 fIndPoints= new Index[fNPoints];
00412 for (Index i=0; i<fNPoints; i++) fIndPoints[i] = i;
00413 fAxis = new UChar_t[fNNodes];
00414 fValue = new Value[fNNodes];
00415
00416 fCrossNode = (1<<(fRowT0+1))-1;
00417 if (fCrossNode<fNNodes) fCrossNode = 2*fCrossNode+1;
00418
00419
00420 Int_t over = (fNNodes+1)-(1<<fRowT0);
00421 Int_t filled = ((1<<fRowT0)-over)*fBucketSize;
00422 fOffset = fNPoints-filled;
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 Int_t rowStack[128];
00433 Int_t nodeStack[128];
00434 Int_t npointStack[128];
00435 Int_t posStack[128];
00436 Int_t currentIndex = 0;
00437 Int_t iter =0;
00438 rowStack[0] = 0;
00439 nodeStack[0] = 0;
00440 npointStack[0] = fNPoints;
00441 posStack[0] = 0;
00442
00443 Int_t nbucketsall =0;
00444 while (currentIndex>=0){
00445 iter++;
00446
00447 Int_t npoints = npointStack[currentIndex];
00448 if (npoints<=fBucketSize) {
00449
00450 currentIndex--;
00451 nbucketsall++;
00452 continue;
00453 }
00454 Int_t crow = rowStack[currentIndex];
00455 Int_t cpos = posStack[currentIndex];
00456 Int_t cnode = nodeStack[currentIndex];
00457
00458
00459
00460 Int_t nbuckets0 = npoints/fBucketSize;
00461 if (npoints%fBucketSize) nbuckets0++;
00462 Int_t restRows = fRowT0-rowStack[currentIndex];
00463 if (restRows<0) restRows =0;
00464 for (;nbuckets0>(2<<restRows); restRows++) {}
00465 Int_t nfull = 1<<restRows;
00466 Int_t nrest = nbuckets0-nfull;
00467 Int_t nleft =0, nright =0;
00468
00469 if (nrest>(nfull/2)){
00470 nleft = nfull*fBucketSize;
00471 nright = npoints-nleft;
00472 }else{
00473 nright = nfull*fBucketSize/2;
00474 nleft = npoints-nright;
00475 }
00476
00477
00478
00479 Value maxspread=0;
00480 Value tempspread, min, max;
00481 Index axspread=0;
00482 Value *array;
00483 for (Int_t idim=0; idim<fNDim; idim++){
00484 array = fData[idim];
00485 Spread(npoints, array, fIndPoints+cpos, min, max);
00486 tempspread = max - min;
00487 if (maxspread < tempspread) {
00488 maxspread=tempspread;
00489 axspread = idim;
00490 }
00491 if(cnode) continue;
00492
00493 fRange[2*idim] = min; fRange[2*idim+1] = max;
00494 }
00495 array = fData[axspread];
00496 KOrdStat(npoints, array, nleft, fIndPoints+cpos);
00497 fAxis[cnode] = axspread;
00498 fValue[cnode] = array[fIndPoints[cpos+nleft]];
00499
00500
00501
00502 npointStack[currentIndex] = nleft;
00503 rowStack[currentIndex] = crow+1;
00504 posStack[currentIndex] = cpos;
00505 nodeStack[currentIndex] = cnode*2+1;
00506 currentIndex++;
00507 npointStack[currentIndex] = nright;
00508 rowStack[currentIndex] = crow+1;
00509 posStack[currentIndex] = cpos+nleft;
00510 nodeStack[currentIndex] = (cnode*2)+2;
00511
00512 if (0){
00513
00514 Info("Build()", "%s", Form("points %d left %d right %d", npoints, nleft, nright));
00515 if (nleft<nright) Warning("Build", "Problem Left-Right");
00516 if (nleft<0 || nright<0) Warning("Build()", "Problem Negative number");
00517 }
00518 }
00519 }
00520
00521
00522 template <typename Index, typename Value>
00523 void TKDTree<Index, Value>::FindNearestNeighbors(const Value *point, const Int_t kNN, Index *ind, Value *dist)
00524 {
00525
00526
00527
00528
00529
00530 if (!ind || !dist) {
00531 Error("FindNearestNeighbors", "Working arrays must be allocated by the user!");
00532 return;
00533 }
00534 for (Int_t i=0; i<kNN; i++){
00535 dist[i]=std::numeric_limits<Value>::max();
00536 ind[i]=-1;
00537 }
00538 MakeBoundariesExact();
00539 UpdateNearestNeighbors(0, point, kNN, ind, dist);
00540
00541 }
00542
00543
00544 template <typename Index, typename Value>
00545 void TKDTree<Index, Value>::UpdateNearestNeighbors(Index inode, const Value *point, Int_t kNN, Index *ind, Value *dist)
00546 {
00547
00548
00549 Value min=0;
00550 Value max=0;
00551 DistanceToNode(point, inode, min, max);
00552 if (min > dist[kNN-1]){
00553
00554 return;
00555 }
00556 if (IsTerminal(inode)) {
00557
00558 Index f1, l1, f2, l2;
00559 GetNodePointsIndexes(inode, f1, l1, f2, l2);
00560 for (Int_t ipoint=f1; ipoint<=l1; ipoint++){
00561 Double_t d = Distance(point, fIndPoints[ipoint]);
00562 if (d<dist[kNN-1]){
00563
00564 Int_t ishift=0;
00565 while(ishift<kNN && d>dist[ishift])
00566 ishift++;
00567
00568
00569 for (Int_t i=kNN-1; i>ishift; i--){
00570 dist[i]=dist[i-1];
00571 ind[i]=ind[i-1];
00572 }
00573 dist[ishift]=d;
00574 ind[ishift]=fIndPoints[ipoint];
00575 }
00576 }
00577 return;
00578 }
00579 if (point[fAxis[inode]]<fValue[inode]){
00580
00581 UpdateNearestNeighbors(GetLeft(inode), point, kNN, ind, dist);
00582 UpdateNearestNeighbors(GetRight(inode), point, kNN, ind, dist);
00583 } else {
00584 UpdateNearestNeighbors(GetRight(inode), point, kNN, ind, dist);
00585 UpdateNearestNeighbors(GetLeft(inode), point, kNN, ind, dist);
00586 }
00587 }
00588
00589
00590 template <typename Index, typename Value>
00591 Double_t TKDTree<Index, Value>::Distance(const Value *point, Index ind, Int_t type) const
00592 {
00593
00594
00595
00596 Double_t dist = 0;
00597 if (type==2){
00598 for (Int_t idim=0; idim<fNDim; idim++){
00599 dist+=(point[idim]-fData[idim][ind])*(point[idim]-fData[idim][ind]);
00600 }
00601 return TMath::Sqrt(dist);
00602 } else {
00603 for (Int_t idim=0; idim<fNDim; idim++){
00604 dist+=TMath::Abs(point[idim]-fData[idim][ind]);
00605 }
00606
00607 return dist;
00608 }
00609 return -1;
00610
00611 }
00612
00613
00614 template <typename Index, typename Value>
00615 void TKDTree<Index, Value>::DistanceToNode(const Value *point, Index inode, Value &min, Value &max, Int_t type)
00616 {
00617
00618
00619
00620
00621 Value *bound = GetBoundaryExact(inode);
00622 min = 0;
00623 max = 0;
00624 Double_t dist1, dist2;
00625
00626 if (type==2){
00627 for (Int_t idim=0; idim<fNDimm; idim+=2){
00628 dist1 = (point[idim/2]-bound[idim])*(point[idim/2]-bound[idim]);
00629 dist2 = (point[idim/2]-bound[idim+1])*(point[idim/2]-bound[idim+1]);
00630
00631 if (point[idim/2]<bound[idim] || point[idim/2]>bound[idim+1])
00632 min+= (dist1>dist2)? dist2 : dist1;
00633
00634 max+= (dist1>dist2)? dist1 : dist2;
00635 }
00636 min = TMath::Sqrt(min);
00637 max = TMath::Sqrt(max);
00638 } else {
00639 for (Int_t idim=0; idim<fNDimm; idim+=2){
00640 dist1 = TMath::Abs(point[idim/2]-bound[idim]);
00641 dist2 = TMath::Abs(point[idim/2]-bound[idim+1]);
00642
00643 min+= (dist1>dist2)? dist2 : dist1;
00644
00645 max+= (dist1>dist2)? dist1 : dist2;
00646 }
00647 }
00648 }
00649
00650
00651 template <typename Index, typename Value>
00652 Index TKDTree<Index, Value>::FindNode(const Value * point) const
00653 {
00654
00655
00656
00657
00658 Index stackNode[128], inode;
00659 Int_t currentIndex =0;
00660 stackNode[0] = 0;
00661 while (currentIndex>=0){
00662 inode = stackNode[currentIndex];
00663 if (IsTerminal(inode)) return inode;
00664
00665 currentIndex--;
00666 if (point[fAxis[inode]]<=fValue[inode]){
00667 currentIndex++;
00668 stackNode[currentIndex]=(inode<<1)+1;
00669 }
00670 if (point[fAxis[inode]]>=fValue[inode]){
00671 currentIndex++;
00672 stackNode[currentIndex]=(inode+1)<<1;
00673 }
00674 }
00675
00676 return -1;
00677 }
00678
00679
00680
00681
00682 template <typename Index, typename Value>
00683 void TKDTree<Index, Value>::FindPoint(Value * point, Index &index, Int_t &iter){
00684
00685
00686
00687
00688 Int_t stackNode[128];
00689 Int_t currentIndex =0;
00690 stackNode[0] = 0;
00691 iter =0;
00692
00693 while (currentIndex>=0){
00694 iter++;
00695 Int_t inode = stackNode[currentIndex];
00696 currentIndex--;
00697 if (IsTerminal(inode)){
00698
00699 Int_t indexIP = (inode >= fCrossNode) ? (inode-fCrossNode)*fBucketSize : (inode-fNNodes)*fBucketSize+fOffset;
00700 printf("terminal %d indexP %d\n", inode, indexIP);
00701 for (Int_t ibucket=0;ibucket<fBucketSize;ibucket++){
00702 Bool_t isOK = kTRUE;
00703 indexIP+=ibucket;
00704 printf("ibucket %d index %d\n", ibucket, indexIP);
00705 if (indexIP>=fNPoints) continue;
00706 Int_t index0 = fIndPoints[indexIP];
00707 for (Int_t idim=0;idim<fNDim;idim++) if (fData[idim][index0]!=point[idim]) isOK = kFALSE;
00708 if (isOK) index = index0;
00709 }
00710 continue;
00711 }
00712
00713 if (point[fAxis[inode]]<=fValue[inode]){
00714 currentIndex++;
00715 stackNode[currentIndex]=(inode*2)+1;
00716 }
00717 if (point[fAxis[inode]]>=fValue[inode]){
00718 currentIndex++;
00719 stackNode[currentIndex]=(inode*2)+2;
00720 }
00721 }
00722
00723
00724 }
00725
00726
00727 template <typename Index, typename Value>
00728 void TKDTree<Index, Value>::FindInRange(Value * point, Value range, std::vector<Index> &res)
00729 {
00730
00731
00732
00733
00734
00735 MakeBoundariesExact();
00736 UpdateRange(0, point, range, res);
00737 }
00738
00739
00740 template <typename Index, typename Value>
00741 void TKDTree<Index, Value>::UpdateRange(Index inode, Value* point, Value range, std::vector<Index> &res)
00742 {
00743
00744
00745 Value min, max;
00746 DistanceToNode(point, inode, min, max);
00747 if (min>range) {
00748
00749 return;
00750 }
00751 if (max<range && max>0) {
00752
00753
00754 Index f1, l1, f2, l2;
00755 GetNodePointsIndexes(inode, f1, l1, f2, l2);
00756
00757 for (Int_t ipoint=f1; ipoint<=l1; ipoint++){
00758 res.push_back(fIndPoints[ipoint]);
00759 }
00760 for (Int_t ipoint=f2; ipoint<=l2; ipoint++){
00761 res.push_back(fIndPoints[ipoint]);
00762 }
00763 return;
00764 }
00765
00766
00767 if (IsTerminal(inode)){
00768
00769 Index f1, l1, f2, l2;
00770 Double_t d;
00771 GetNodePointsIndexes(inode, f1, l1, f2, l2);
00772 for (Int_t ipoint=f1; ipoint<=l1; ipoint++){
00773 d = Distance(point, fIndPoints[ipoint]);
00774 if (d <= range){
00775 res.push_back(fIndPoints[ipoint]);
00776 }
00777 }
00778 return;
00779 }
00780 if (point[fAxis[inode]]<=fValue[inode]){
00781
00782 UpdateRange(GetLeft(inode),point, range, res);
00783 UpdateRange(GetRight(inode),point, range, res);
00784 } else {
00785 UpdateRange(GetLeft(inode),point, range, res);
00786 UpdateRange(GetRight(inode),point, range, res);
00787 }
00788 }
00789
00790
00791 template <typename Index, typename Value>
00792 Index* TKDTree<Index, Value>::GetPointsIndexes(Int_t node) const
00793 {
00794
00795
00796
00797
00798 if (!IsTerminal(node)){
00799 printf("GetPointsIndexes() only for terminal nodes, use GetNodePointsIndexes() instead\n");
00800 return 0;
00801 }
00802 Int_t offset = (node >= fCrossNode) ? (node-fCrossNode)*fBucketSize : fOffset+(node-fNNodes)*fBucketSize;
00803 return &fIndPoints[offset];
00804 }
00805
00806
00807 template <typename Index, typename Value>
00808 void TKDTree<Index, Value>::GetNodePointsIndexes(Int_t node, Int_t &first1, Int_t &last1, Int_t &first2, Int_t &last2) const
00809 {
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 if (IsTerminal(node)){
00829
00830 Index offset = (node >= fCrossNode) ? (node-fCrossNode)*fBucketSize : fOffset+(node-fNNodes)*fBucketSize;
00831 first1 = offset;
00832 last1 = offset + GetNPointsNode(node)-1;
00833 first2 = 0;
00834 last2 = -1;
00835 return;
00836 }
00837
00838 Index firsttermnode = fNNodes;
00839 Index ileft = node;
00840 Index iright = node;
00841 Index f1, l1, f2, l2;
00842
00843 while (ileft<firsttermnode)
00844 ileft = GetLeft(ileft);
00845
00846 while (iright<firsttermnode)
00847 iright = GetRight(iright);
00848
00849 if (ileft>iright){
00850
00851
00852
00853
00854 GetNodePointsIndexes(firsttermnode, f1, l1, f2, l2);
00855 first1 = f1;
00856 GetNodePointsIndexes(iright, f1, l1, f2, l2);
00857 last1 = l1;
00858 GetNodePointsIndexes(ileft, f1, l1, f2, l2);
00859 first2 = f1;
00860 GetNodePointsIndexes(fTotalNodes-1, f1, l1, f2, l2);
00861 last2 = l1;
00862
00863 } else {
00864 GetNodePointsIndexes(ileft, f1, l1, f2, l2);
00865 first1 = f1;
00866 GetNodePointsIndexes(iright, f1, l1, f2, l2);
00867 last1 = l1;
00868 first2 = 0;
00869 last2 = -1;
00870 }
00871 }
00872
00873
00874 template <typename Index, typename Value>
00875 Index TKDTree<Index, Value>::GetNPointsNode(Int_t inode) const
00876 {
00877
00878
00879
00880
00881 if (IsTerminal(inode)){
00882
00883 if (inode!=fTotalNodes-1) return fBucketSize;
00884 else {
00885 if (fOffset%fBucketSize==0) return fBucketSize;
00886 else return fOffset%fBucketSize;
00887 }
00888 }
00889
00890 Int_t f1, l1, f2, l2;
00891 GetNodePointsIndexes(inode, f1, l1, f2, l2);
00892 Int_t sum = l1-f1+1;
00893 sum += l2-f2+1;
00894 return sum;
00895 }
00896
00897
00898
00899 template <typename Index, typename Value>
00900 void TKDTree<Index, Value>::SetData(Index npoints, Index ndim, UInt_t bsize, Value **data)
00901 {
00902
00903
00904
00905
00906
00907
00908
00909 Clear();
00910
00911
00912 fData = data;
00913 fNPoints = npoints;
00914 fNDim = ndim;
00915 fBucketSize = bsize;
00916
00917 Build();
00918 }
00919
00920
00921 template <typename Index, typename Value>
00922 Int_t TKDTree<Index, Value>::SetData(Index idim, Value *data)
00923 {
00924
00925
00926
00927
00928
00929 if (fAxis || fValue) {
00930 Error("SetData", "The tree has already been built, no updates possible");
00931 return 0;
00932 }
00933
00934 if (!fData) {
00935 fData = new Value*[fNDim];
00936 }
00937 fData[idim]=data;
00938 fDataOwner = 2;
00939 return 1;
00940 }
00941
00942
00943
00944 template <typename Index, typename Value>
00945 void TKDTree<Index, Value>::Spread(Index ntotal, Value *a, Index *index, Value &min, Value &max) const
00946 {
00947
00948
00949 Index i;
00950 min = a[index[0]];
00951 max = a[index[0]];
00952 for (i=0; i<ntotal; i++){
00953 if (a[index[i]]<min) min = a[index[i]];
00954 if (a[index[i]]>max) max = a[index[i]];
00955 }
00956 }
00957
00958
00959
00960 template <typename Index, typename Value>
00961 Value TKDTree<Index, Value>::KOrdStat(Index ntotal, Value *a, Index k, Index *index) const
00962 {
00963
00964
00965
00966 Index i, ir, j, l, mid;
00967 Index arr;
00968 Index temp;
00969
00970 Index rk = k;
00971 l=0;
00972 ir = ntotal-1;
00973 for(;;) {
00974 if (ir<=l+1) {
00975 if (ir == l+1 && a[index[ir]]<a[index[l]])
00976 {temp = index[l]; index[l]=index[ir]; index[ir]=temp;}
00977 Value tmp = a[index[rk]];
00978 return tmp;
00979 } else {
00980 mid = (l+ir) >> 1;
00981 {temp = index[mid]; index[mid]=index[l+1]; index[l+1]=temp;}
00982 if (a[index[l]]>a[index[ir]])
00983 {temp = index[l]; index[l]=index[ir]; index[ir]=temp;}
00984
00985 if (a[index[l+1]]>a[index[ir]])
00986 {temp=index[l+1]; index[l+1]=index[ir]; index[ir]=temp;}
00987
00988 if (a[index[l]]>a[index[l+1]])
00989 {temp = index[l]; index[l]=index[l+1]; index[l+1]=temp;}
00990
00991 i=l+1;
00992 j=ir;
00993 arr = index[l+1];
00994 for (;;) {
00995 do i++; while (a[index[i]]<a[arr]);
00996 do j--; while (a[index[j]]>a[arr]);
00997 if (j<i) break;
00998 {temp=index[i]; index[i]=index[j]; index[j]=temp;}
00999 }
01000 index[l+1]=index[j];
01001 index[j]=arr;
01002 if (j>=rk) ir = j-1;
01003 if (j<=rk) l=i;
01004 }
01005 }
01006 }
01007
01008
01009 template <typename Index, typename Value>
01010 void TKDTree<Index, Value>::MakeBoundaries(Value *range)
01011 {
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021 if(range) memcpy(fRange, range, fNDimm*sizeof(Value));
01022
01023 Int_t totNodes = fNNodes + fNPoints/fBucketSize + ((fNPoints%fBucketSize)?1:0);
01024 fBoundaries = new Value[totNodes*fNDimm];
01025
01026
01027
01028
01029 Value *tbounds = 0x0, *cbounds = 0x0;
01030 Int_t cn;
01031 for(int inode=fNNodes-1; inode>=0; inode--){
01032 tbounds = &fBoundaries[inode*fNDimm];
01033 memcpy(tbounds, fRange, fNDimm*sizeof(Value));
01034
01035
01036 cn = (inode<<1)+1;
01037 if(IsTerminal(cn)) CookBoundaries(inode, kTRUE);
01038 cbounds = &fBoundaries[fNDimm*cn];
01039 for(int idim=0; idim<fNDim; idim++) tbounds[idim<<1] = cbounds[idim<<1];
01040
01041
01042 cn = (inode+1)<<1;
01043 if(IsTerminal(cn)) CookBoundaries(inode, kFALSE);
01044 cbounds = &fBoundaries[fNDimm*cn];
01045 for(int idim=0; idim<fNDim; idim++) tbounds[(idim<<1)+1] = cbounds[(idim<<1)+1];
01046 }
01047 }
01048
01049
01050 template <typename Index, typename Value>
01051 void TKDTree<Index, Value>::CookBoundaries(const Int_t node, Bool_t LEFT)
01052 {
01053
01054 Int_t index = (node<<1) + (LEFT ? 1 : 2);
01055
01056
01057
01058 Value *tbounds = &fBoundaries[fNDimm*index];
01059 memcpy(tbounds, fRange, fNDimm*sizeof(Value));
01060 Bool_t flag[256];
01061 memset(flag, kFALSE, fNDimm);
01062 Int_t nvals = 0;
01063
01064
01065 Int_t pn = node;
01066 while(pn >= 0 && nvals < fNDimm){
01067 if(LEFT){
01068 index = (fAxis[pn]<<1)+1;
01069 if(!flag[index]) {
01070 tbounds[index] = fValue[pn];
01071 flag[index] = kTRUE;
01072 nvals++;
01073 }
01074 } else {
01075 index = fAxis[pn]<<1;
01076 if(!flag[index]) {
01077 tbounds[index] = fValue[pn];
01078 flag[index] = kTRUE;
01079 nvals++;
01080 }
01081 }
01082 LEFT = pn&1;
01083 pn = (pn - 1)>>1;
01084 }
01085 }
01086
01087
01088 template <typename Index, typename Value>
01089 void TKDTree<Index, Value>::MakeBoundariesExact()
01090 {
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102 if (fBoundaries){
01103
01104 return;
01105 }
01106 fBoundaries = new Value[fTotalNodes*fNDimm];
01107 Value *min = new Value[fNDim];
01108 Value *max = new Value[fNDim];
01109 for (Index inode=fNNodes; inode<fTotalNodes; inode++){
01110
01111 for (Index idim=0; idim<fNDim; idim++){
01112 min[idim]= std::numeric_limits<Value>::max();
01113 max[idim]=-std::numeric_limits<Value>::max();
01114 }
01115 Index *points = GetPointsIndexes(inode);
01116 Index npoints = GetNPointsNode(inode);
01117
01118 for (Index ipoint=0; ipoint<npoints; ipoint++){
01119 for (Index idim=0; idim<fNDim; idim++){
01120 if (fData[idim][points[ipoint]]<min[idim])
01121 min[idim]=fData[idim][points[ipoint]];
01122 if (fData[idim][points[ipoint]]>max[idim])
01123 max[idim]=fData[idim][points[ipoint]];
01124 }
01125 }
01126 for (Index idim=0; idim<fNDimm; idim+=2){
01127 fBoundaries[inode*fNDimm + idim]=min[idim/2];
01128 fBoundaries[inode*fNDimm + idim+1]=max[idim/2];
01129 }
01130 }
01131
01132 delete [] min;
01133 delete [] max;
01134
01135 Index left, right;
01136 for (Index inode=fNNodes-1; inode>=0; inode--){
01137
01138 left = GetLeft(inode)*fNDimm;
01139 right = GetRight(inode)*fNDimm;
01140 for (Index idim=0; idim<fNDimm; idim+=2){
01141
01142 fBoundaries[inode*fNDimm+idim]=TMath::Min(fBoundaries[left+idim], fBoundaries[right+idim]);
01143
01144 fBoundaries[inode*fNDimm+idim+1]=TMath::Max(fBoundaries[left+idim+1], fBoundaries[right+idim+1]);
01145
01146 }
01147 }
01148 }
01149
01150
01151 template <typename Index, typename Value>
01152 void TKDTree<Index, Value>::FindBNodeA(Value *point, Value *delta, Int_t &inode){
01153
01154
01155
01156 inode =0;
01157 for (;inode<fNNodes;){
01158 if (TMath::Abs(point[fAxis[inode]] - fValue[inode])<delta[fAxis[inode]]) break;
01159 inode = (point[fAxis[inode]] < fValue[inode]) ? (inode*2)+1: (inode*2)+2;
01160 }
01161 }
01162
01163
01164 template <typename Index, typename Value>
01165 Value* TKDTree<Index, Value>::GetBoundaries()
01166 {
01167
01168 if(!fBoundaries) MakeBoundaries();
01169 return fBoundaries;
01170 }
01171
01172
01173
01174 template <typename Index, typename Value>
01175 Value* TKDTree<Index, Value>::GetBoundariesExact()
01176 {
01177
01178 if(!fBoundaries) MakeBoundariesExact();
01179 return fBoundaries;
01180 }
01181
01182
01183 template <typename Index, typename Value>
01184 Value* TKDTree<Index, Value>::GetBoundary(const Int_t node)
01185 {
01186
01187 if(!fBoundaries) MakeBoundaries();
01188 return &fBoundaries[node*2*fNDim];
01189 }
01190
01191
01192 template <typename Index, typename Value>
01193 Value* TKDTree<Index, Value>::GetBoundaryExact(const Int_t node)
01194 {
01195
01196 if(!fBoundaries) MakeBoundariesExact();
01197 return &fBoundaries[node*2*fNDim];
01198 }
01199
01200
01201
01202 TKDTreeIF *TKDTreeTestBuild(const Int_t npoints, const Int_t bsize){
01203
01204
01205
01206 Float_t *data0 = new Float_t[npoints*2];
01207 Float_t *data[2];
01208 data[0] = &data0[0];
01209 data[1] = &data0[npoints];
01210 for (Int_t i=0;i<npoints;i++) {
01211 data[1][i]= gRandom->Rndm();
01212 data[0][i]= gRandom->Rndm();
01213 }
01214 TKDTree<Int_t, Float_t> *kdtree = new TKDTreeIF(npoints, 2, bsize, data);
01215 return kdtree;
01216 }
01217
01218
01219
01220 template class TKDTree<Int_t, Float_t>;
01221 template class TKDTree<Int_t, Double_t>;