9 static int gMyId=0,gMyInst=0;
11 #include "StMultiKeyMapM.h"
13 #define MAX(a,b) ((a) > (b) ? (a) : (b))
14 #define MIN(a,b) ((a) < (b) ? (a) : (b))
16 static void random_shuffle(std::vector<StMultiKeyNode*> &arr);
18 StMultiKeyMapM::StMultiKeyMapM(
int nkeys)
24 StMultiKeyMapM::~StMultiKeyMapM()
29 void StMultiKeyMapM::Clear(
const char *)
35 void StMultiKeyMapM::Add(
const void *obj,
const double *keys)
38 for (
int i=0;i<mNKey;i++) {buf[i]=(float)keys[i];}
42 void StMultiKeyMapM::Add(
const void *obj,
const float *keys)
51 double StMultiKeyMapM::StMultiKeyMapM::Quality()
54 return mTop->Quality();
57 int StMultiKeyMapM::MakeTree(
int keepArray)
59 int nNodes = mArr.size();
60 if (!nNodes)
return 0;
64 if (!mTop ) {mTop = mArr[0];jl=1;mTop->SetIKey(0);}
65 unsigned int myRnd = 1946;
66 for (
int i=jl;i<nNodes;i++) {
67 myRnd+=1000000007; mArr[i]->SetIKey(myRnd%mNKey);
71 if (keepArray)
return nNodes;
72 std::vector<StMultiKeyNode*> tmp(0);
78 int StMultiKeyMapM::ls(
const char *file)
const
80 return mTop->ls(file);
83 int StMultiKeyMapM::Size()
const
85 if (mTop)
return mTop->Size();
86 else return mArr.size();
90 StMultiKeyNode::StMultiKeyNode(
int nKeys)
100 if (fr.mObj) Set(fr.mObj,fr.mKeys);
103 void StMultiKeyNode::Init()
105 memset(&mNKey,0,(
char*)&mKeys-&mNKey+
sizeof(mKeys));
106 mId = ++gMyId; gMyInst++; mIKey = -1;
109 void StMultiKeyNode::Clear()
111 memset(&mIKey,0,(
char*)&mObj - &mIKey); mIKey = -1;
114 StMultiKeyNode::~StMultiKeyNode()
122 int StMultiKeyNode::GetNInst()
125 void StMultiKeyNode::Set(
const void *obj,
const float *keys)
128 mObj = obj; mIKey=-1;
129 if (!mKeys) mKeys =
new float[mNKey];
130 memcpy(mKeys,keys,
sizeof(mKeys[0])*mNKey);
133 void StMultiKeyNode::Set(
const void *obj,
const double *keys)
136 for (
int i=0;i<mNKey;i++) {buf[i]=(float)keys[i];}
140 void StMultiKeyNode::Add(
const void *obj,
const float *keys)
149 static int nCall=0; nCall++;
150 assert(
this != node);
151 int way = (node->mKeys[int(mIKey)] > GetKey());
152 if (mLink[way]) { mLink[way]->Add(node);}
153 else { mLink[way] = node ;}
158 double StMultiKeyNode::Quality()
161 int nTot = GetNumb(0)+GetNumb(1)+1;
167 int nL = node->GetNumb(0);
168 int nR = node->GetNumb(1);
169 if (!nL || !nR)
continue;
170 qa += (2.*nL*nR+nL+nR)/nTot;
172 printf(
"Quality() nodes %d\n",n);
176 int StMultiKeyNode::ls(
const char *file)
const
180 if (file && file[0]) out=fopen(file,
"w");
188 int nL = node->GetNumb(0);
189 int nR = node->GetNumb(1);
190 int lev = iter.Level();
191 if (node==
this) {fprintf(out,
"%4d * ",n);}
192 else {fprintf(out,
"%4d - ",n);}
193 fprintf(out,
"Lev(%d) \t(%10p) \tL(%10p(%d)) \tR(%10p(%d)) \tDiv(%g)"
195 ,(
void*)node->mLink[0],nL
196 ,(
void*)node->mLink[1],nR
199 for (
int j=0;j<mNKey;j++) {fprintf(out,
" %g",node->mKeys[j]);}}
208 StMultiKeyMapMIter::StMultiKeyMapMIter(
const StMultiKeyNode *node,
const float *kMin,
const float *kMax)
215 void StMultiKeyMapMIter::Set(
const StMultiKeyNode *node,
const float *kMin,
const float *kMax)
217 memset(mTouched,0,
sizeof(mTouched));
219 mNK = node->GetNKey();
222 mMinMax.resize(2*mNK);
225 int sk = mNK*
sizeof(mKMin[0]);
226 memcpy(mKMin,kMin,sk);
227 memcpy(mKMax,kMax,sk);
232 if (FullCheck()) ++(*this);
235 void StMultiKeyMapMIter::Update(
const float *kMin,
const float *kMax)
237 int sk = mNK*
sizeof(mKMin[0]);
238 if (kMin) memcpy(mKMin,kMin,sk);
239 if (kMax) memcpy(mKMax,kMax,sk);
242 StMultiKeyMapMIter::~StMultiKeyMapMIter()
252 if (rLink && (!mKMin || !FilterRite(node))) Left(rLink);
253 if (!FullCheck())
break;
261 if ((
int)mStk.size() <=mLev) mStk.resize(mLev*2);
263 if (!node->LLink())
break;
264 if (mKMin && FilterLeft(node))
break;
265 node = node->LLink();
270 int StMultiKeyMapMIter::FullCheck()
274 if (!node )
return 0;
275 if (!mKMin)
return 0;
277 const float *fk = node->GetKeys();
279 for (
int k=0;k<mNK;k++) {
280 if (mKMin[k]>fk[k] || fk[k] >= mKMax[k])
return 1;
285 int StMultiKeyMapMIter::FilterLeft(
const StMultiKeyNode *node)
const
287 int ik = node->GetIKey();
288 float fk = node->GetKey();
290 return ( mKMin[ik]>fk);
293 int StMultiKeyMapMIter::FilterRite(
const StMultiKeyNode *node)
const
295 int ik = node->GetIKey();
296 float fk = node->GetKey();
298 return (mKMax[ik]<=fk);
301 void random_shuffle(std::vector<StMultiKeyNode*> &arr)
303 static const unsigned int us=1000000007;
304 int n = arr.size();
if (n<=3)
return;
316 void StMultiKeyMapM::Test()
318 printf(
"StMultiKeyMapM::Test() started\n");
322 for (
int i=0;i<nEVTS;i++) {
323 rnd = 1 - (i+1.)/nEVTS;
324 map.Add((
void*)(-1),&rnd);
328 double qa = map.Quality();
329 printf(
" Quality of tree = %g\n\n",qa);
335 printf(
"\n%d evts No bounds\n",nEVTS);
338 n++; rnd = node->GetKeys()[0];
344 printf(
"\nNo bounds OK, touched %d %d %d\n"
345 ,iter.Touched()[0],iter.Touched()[1],iter.Touched()[2]);
348 float kMin=0.5,kMax=0.6;
349 iter.Set(map.GetTop(),&kMin,&kMax);
351 int nEst = int((nEVTS)*(kMax-kMin)+0.5);
352 printf(
"\n%d ~evts bounds=%g %g\n",nEst,kMin,kMax);
355 n++; rnd = node->GetKeys()[0];
358 assert((kMin<=rnd) && (rnd < kMax));
361 printf(
"\nGot %d. Bounds OK, Touched %d %d %d\n",n
362 ,iter.Touched()[0],iter.Touched()[1],iter.Touched()[2]);
366 void StMultiKeyMapM::Test2()
368 printf(
"StMultiKeyMapM::Test2() started\n");
372 for (
int iEv=0;iEv<nEvts ;iEv++) {
373 for (
int ik=0;ik<4;ik++) { key[ik]= gRandom->Rndm();}
374 map.Add((
void*)1,key);
379 double qa = map.Quality();
380 printf(
" Quality of tree = %g\n\n",qa);
383 float dow[4]={0, 0.1,0.2,0.3};
384 float upp[4]={0.2,0.3,0.4,0.5};
387 double ev = nEvts;
for (
int i=0;i<4;i++){ev*=(upp[i]-dow[i]);};
388 printf(
"\n%d ~evts \n",
int(ev+0.5));
389 int nk = map.GetNKey();
393 nSel++;
int good = 0;
394 const float *key = node->GetKeys();
395 for (
int j=0;j<nk;j++) {
if (key[j]>=dow[j] && key[j]<upp[j]) good++;}
402 for (
int i=0;i<nb;i++)
405 const float *key = node->GetKeys();
407 for (
int k=0;k<nk;k++) {
408 if (dow[k]<=key[k] && key[k] < upp[k])
continue;
415 printf(
"\nSelected %d bad %d and must be %d\n",nSel,nBad,nMust);
416 printf(
"Touched %d %d %d\n"
417 ,iter.Touched()[0],iter.Touched()[1],iter.Touched()[2]);