Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TEntryListBlock.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id$
2// Author: Anna Kreshuk 27/10/2006
3
4/*************************************************************************
5 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TEntryListBlock
13\ingroup tree
14
15Used by TEntryList to store the entry numbers.
16
17There are 2 ways to represent entry numbers in a TEntryListBlock:
18
19 1. as bits, where passing entry numbers are assigned 1, not passing - 0
20 2. as a simple array of entry numbers
21 - storing the numbers of entries that pass
22 - storing the numbers of entries that don't pass
23
24In both cases, a UShort_t* is used. The second option is better in case
25less than 1/16 or more than 15/16 of entries pass the selection, and the representation can be
26changed by calling OptimizeStorage() function.
27When the block is being filled, it's always stored as bits, and the OptimizeStorage()
28function is called by TEntryList when it starts filling the next block. If
29Enter() or Remove() is called after OptimizeStorage(), representation is
30again changed to 1).
31
32Begin_Macro
33entrylistblock_figure1.C
34End_Macro
35
36## Operations on blocks (see also function comments)
37
38 - __Merge__() - adds all entries from one block to the other. If the first block
39 uses array representation, it's changed to bits representation only
40 if the total number of passing entries is still less than kBlockSize
41 - __GetEntry(n)__ - returns n-th non-zero entry.
42 - __Next__() - return next non-zero entry. In case of representation 1), Next()
43 is faster than GetEntry()
44*/
45
46#include "TEntryListBlock.h"
47#include "TString.h"
48
49
50////////////////////////////////////////////////////////////////////////////////
51/// Default c-tor
54{
55 fIndices = nullptr;
56 fN = kBlockSize;
57 fNPassed = 0;
58 fType = -1;
59 fPassing = true;
60 fCurrent = 0;
63}
64
65////////////////////////////////////////////////////////////////////////////////
66/// Copy c-tor
69{
70 fN = eblock.fN;
71 if (eblock.fIndices){
72 fIndices = new UShort_t[fN];
73 for (Int_t i=0; i<fN; i++)
74 fIndices[i] = eblock.fIndices[i];
75 } else {
76 fIndices = nullptr;
77 }
78 fNPassed = eblock.fNPassed;
79 fType = eblock.fType;
80 fPassing = eblock.fPassing;
81 fCurrent = eblock.fCurrent;
84}
85
86////////////////////////////////////////////////////////////////////////////////
87/// Destructor
90{
91 if (fIndices)
92 delete [] fIndices;
93 fIndices = nullptr;
94}
95
96////////////////////////////////////////////////////////////////////////////////
99{
100 if (this != &eblock) {
101 if (fIndices)
102 delete [] fIndices;
103
104 fN = eblock.fN;
105 if (eblock.fIndices){
106 fIndices = new UShort_t[fN];
107 for (Int_t i=0; i<fN; i++)
108 fIndices[i] = eblock.fIndices[i];
109 } else {
110 fIndices = nullptr;
111 }
112 fNPassed = eblock.fNPassed;
113 fType = eblock.fType;
114 fPassing = eblock.fPassing;
115 fCurrent = eblock.fCurrent;
118 }
119 return *this;
120}
121
122////////////////////////////////////////////////////////////////////////////////
123/// If the block has already been optimized and the entries
124/// are stored as a list and not as bits, trying to enter a new entry
125/// will make the block switch to bits representation
128{
129 if (entry > kBlockSize*16) {
130 Error("Enter", "illegal entry value!");
131 return false;
132 }
133 if (!fIndices){
135 for (Int_t i=0; i<kBlockSize; i++)
136 fIndices[i] = 0;
137 fType = 0; //start in bits
138 }
139 if (fType==0){
140 //bits
141 Int_t i = entry>>4;
142 Int_t j = entry & 15;
143 if ((fIndices[i] & (1<<j))==0){
144 fIndices[i] |= 1<<j;
145 fNPassed++;
146 return true;
147 } else {
148 return false;
149 }
150 }
151 //list
152 //change to bits
153 UShort_t *bits = new UShort_t[kBlockSize];
154 Transform(true, bits);
155 Enter(entry);
156 return false;
157}
158
159////////////////////////////////////////////////////////////////////////////////
160/// Remove entry \#entry
161/// If the block has already been optimized and the entries
162/// are stored as a list and not as bits, trying to remove a new entry
163/// will make the block switch to bits representation
166{
167 if (entry > kBlockSize*16) {
168 Error("Remove", "Illegal entry value!\n");
169 return false;
170 }
171 if (fType==0){
172 Int_t i = entry>>4;
173 Int_t j = entry & 15;
174 if ((fIndices[i] & (1<<j))!=0){
175 fIndices[i] &= (0xFFFF^(1<<j));
176 fNPassed--;
177 return true;
178 } else {
179 return false;
180 }
181 }
182 //list
183 //change to bits
184 UShort_t *bits = new UShort_t[kBlockSize];
185 Transform(true, bits);
186 return Remove(entry);
187 //return 0;
188}
189
190////////////////////////////////////////////////////////////////////////////////
191/// True if the block contains entry \#entry
194{
195 if (entry > kBlockSize*16) {
196 Error("Contains", "Illegal entry value!\n");
197 return 0;
198 }
199 if (!fIndices && fPassing)
200 return 0;
201 if (fType==0 && fIndices){
202 //bits
203 Int_t i = entry>>4;
204 Int_t j = entry & 15;
205 bool result = (fIndices[i] & (1<<j))!=0;
206 return result;
207 }
208 //list
209 if (entry < fCurrent) fCurrent = 0;
210 if (fPassing && fIndices){
211 for (Int_t i = fCurrent; i<fNPassed; i++){
212 if (fIndices[i]==entry){
213 fCurrent = i;
214 return true;
215 }
216 }
217 } else {
218 if (!fIndices || fNPassed==0){
219 //all entries pass
220 return true;
221 }
222 if (entry > fIndices[fNPassed-1])
223 return true;
224 for (Int_t i= fCurrent; i<fNPassed; i++){
225 if (fIndices[i]==entry){
226 fCurrent = i;
227 return false;
228 }
229 if (fIndices[i]>entry){
230 fCurrent = i;
231 return true;
232 }
233 }
234 }
235 return 0;
236}
237
238////////////////////////////////////////////////////////////////////////////////
239/// Merge with the other block
240/// Returns the resulting number of entries in the block
243{
244 Int_t i, j;
245 if (block->GetNPassed() == 0) return GetNPassed();
246 if (GetNPassed() == 0){
247 //this block is empty
248 fN = block->fN;
249 fIndices = new UShort_t[fN];
250 for (i=0; i<fN; i++)
251 fIndices[i] = block->fIndices[i];
252 fNPassed = block->fNPassed;
253 fType = block->fType;
254 fPassing = block->fPassing;
255 fCurrent = block->fCurrent;
258 return fNPassed;
259 }
260 if (fType==0){
261 //stored as bits
262 if (block->fType == 0){
263 for (i=0; i<kBlockSize*16; i++){
264 if (block->Contains(i))
265 Enter(i);
266 }
267 } else {
268 if (block->fPassing){
269 //the other block stores entries that pass
270 for (i=0; i<block->fNPassed; i++){
271 Enter(block->fIndices[i]);
272 }
273 } else {
274 //the other block stores entries that don't pass
275 if (block->fNPassed==0){
276 for (i=0; i<kBlockSize*16; i++){
277 Enter(i);
278 }
279 }
280 for (j=0; j<block->fIndices[0]; j++)
281 Enter(j);
282 for (i=0; i<block->fNPassed-1; i++){
283 for (j=block->fIndices[i]+1; j<block->fIndices[i+1]; j++){
284 Enter(j);
285 }
286 }
287 for (j=block->fIndices[block->fNPassed-1]+1; j<kBlockSize*16; j++)
288 Enter(j);
289 }
290 }
291 } else {
292 //stored as a list
293 if (GetNPassed() + block->GetNPassed() > kBlockSize){
294 //change to bits
295 UShort_t *bits = new UShort_t[kBlockSize];
296 Transform(true, bits);
297 Merge(block);
298 } else {
299 //this is only possible if fPassing=1 in both blocks
300 if (block->fType==1){
301 //second block stored as a list
302 //make a bigger list
303 Int_t en = block->fNPassed;
306 UShort_t *elst = block->fIndices;
308 newpos = elpos = 0;
309 for (i=0; i<fNPassed; i++) {
310 while (elpos < en && fIndices[i] > elst[elpos]) {
312 newpos++;
313 elpos++;
314 }
315 if (fIndices[i] == elst[elpos]) elpos++;
316 newlist[newpos] = fIndices[i];
317 newpos++;
318 }
319 while (elpos < en) {
321 newpos++;
322 elpos++;
323 }
324 delete [] fIndices;
327 fN = fNPassed;
328 } else {
329 //second block is stored as bits
330
331 Int_t en = block->fNPassed;
334 Int_t newpos, current;
335 newpos = current = 0;
336 for (i=0; i<kBlockSize*16; i++){
337 if (!block->Contains(i)) continue;
338 while(current < fNPassed && fIndices[current]<i){
339 newlist[newpos] = fIndices[current];
340 current++;
341 newpos++;
342 }
343 if (fIndices[current]==i) current++;
344 newlist[newpos] = i;
345 newpos++;
346 }
347 while(current<fNPassed){
348 newlist[newpos] = fIndices[current];
349 newpos++;
350 current++;
351 }
352 delete [] fIndices;
355 fN = fNPassed;
356 }
357 }
358 }
362 return GetNPassed();
363}
364
365////////////////////////////////////////////////////////////////////////////////
366/// Returns the number of entries, passing the selection.
367/// In case, when the block stores entries that pass (fPassing=1) returns fNPassed
370{
371 if (fPassing)
372 return fNPassed;
373 else
374 return kBlockSize*16-fNPassed;
375}
376
377////////////////////////////////////////////////////////////////////////////////
378/// Return entry \#entry.
379/// See also Next()
382{
383 if (entry > kBlockSize*16) return -1;
384 if (entry > GetNPassed()) return -1;
385 if (entry == fLastIndexQueried+1) return Next();
386 else {
387 Int_t i=0; Int_t j=0; Int_t entries_found=0;
388 if (fType==0){
389 if ((fIndices[i] & (1<<j))!=0)
391 while (entries_found<entry+1){
392 if (j==15){i++; j=0;}
393 else j++;
394 if ((fIndices[i] & (1<<j))!=0)
396 }
398 fLastIndexReturned = i*16+j;
399 return fLastIndexReturned;
400 }
401 if (fType==1){
402 if (fPassing){
405 return fIndices[entry];
406 } else {
408 if (!fIndices || fNPassed==0){
409 //all entries pass
411 return fLastIndexReturned;
412 }
413 for (i=0; i<fIndices[0]; i++){
415 if (entries_found==entry+1){
417 return fLastIndexReturned;
418 }
419 }
420 for (i=0; i<fNPassed-1; i++){
421 for (j=fIndices[i]+1; j<fIndices[i+1]; j++){
423 if (entries_found==entry+1){
425 return fLastIndexReturned;
426 }
427 }
428 }
429 for (j=fIndices[fNPassed-1]+1; j<kBlockSize*16; j++){
431 if (entries_found==entry+1){
433 return fLastIndexReturned;
434 }
435 }
436 }
437 }
438 return -1;
439 }
440}
441
442////////////////////////////////////////////////////////////////////////////////
443/// Return the next non-zero entry
444/// Faster than GetEntry() function
447{
451 return -1;
452 }
453
454 if (fType==0) {
455 //bits
456 Int_t i=0;
457 Int_t j=0;
459 i = fLastIndexReturned>>4;
460 j = fLastIndexReturned & 15;
461 bool result=(fIndices[i] & (1<<j))!=0;
462 while (!result) {
463 if (j==15) {j=0; i++;}
464 else j++;
465 result = (fIndices[i] & (1<<j)) != 0;
466 }
467 fLastIndexReturned = i*16+j;
469 return fLastIndexReturned;
470
471 }
472 if (fType==1) {
474 if (fPassing){
477 } else {
481 }
482 return fLastIndexReturned;
483 }
484
485 }
486 return -1;
487}
488
489////////////////////////////////////////////////////////////////////////////////
490/// Print the entries in this block
492void TEntryListBlock::Print(const Option_t *option) const
493{
494 TString opt = option;
495 opt.ToUpper();
496 if (opt.Contains("A")) PrintWithShift(0);
497}
498
499////////////////////////////////////////////////////////////////////////////////
500/// Print the indices of this block + shift (used from TEntryList::Print()) to
501/// print the current values
504{
505 Int_t i;
506 if (fType==0){
508 bool result;
509 for (i=0; i<kBlockSize*16; i++){
510 ibite = i>>4;
511 ibit = i & 15;
512 result = (fIndices[ibite] & (1<<ibit))!=0;
513 if (result)
514 printf("%d\n", i+shift);
515 }
516 } else {
517 if (fPassing){
518 for (i=0; i<fNPassed; i++){
519 printf("%d\n", fIndices[i]+shift);
520 }
521 } else {
522 if (fNPassed==0){
523 for (i=0; i<kBlockSize*16; i++)
524 printf("%d\n", i+shift);
525 return;
526 }
527 for (i=0; i<fIndices[0]; i++){
528 printf("%d\n", i+shift);
529 }
530 for (i=0; i<fNPassed-1; i++){
531 for (Int_t j=fIndices[i]+1; j<fIndices[i+1]; j++){
532 printf("%d\n", j+shift);
533 }
534 }
535 for (Int_t j=fIndices[fNPassed-1]+1; j<kBlockSize*16; j++){
536 printf("%d\n", j+shift);
537 }
538 }
539 }
540}
541
542////////////////////////////////////////////////////////////////////////////////
543/// If there are < kBlockSize or >kBlockSize*15 entries, change to an array
544/// representation
547{
548 if (fType!=0) return;
549 if (fNPassed > kBlockSize*15)
550 fPassing = false;
552 //less than 4000 entries passing, makes sense to change from bits to list
554 Transform(false, indexnew);
555 }
556}
557
558////////////////////////////////////////////////////////////////////////////////
559/// Transform the existing fIndices
560/// - dir=0 - transform from bits to a list
561/// - dir=1 - tranform from a list to bits
564{
565 Int_t i=0;
566 Int_t ilist = 0;
568 if (!dir) {
569 for (i=0; i<kBlockSize*16; i++){
570 ibite = i >> 4;
571 ibit = i & 15;
572 bool result = (fIndices[ibite] & (1<<ibit))!=0;
573 if (result && fPassing){
574 //fill with the entries that pass
575 indexnew[ilist] = i;
576 ilist++;
577 }
578 else if (!result && !fPassing){
579 //fill with the entries that don't pass
580 indexnew[ilist] = i;
581 ilist++;
582 }
583 }
584 if (fIndices)
585 delete [] fIndices;
587 fType = 1;
588 if (!fPassing)
590 fN = fNPassed;
591 return;
592 }
593
594 if (fPassing){
595 for (i=0; i<kBlockSize; i++)
596 indexnew[i] = 0;
597 for (i=0; i<fNPassed; i++){
598 ibite = fIndices[i]>>4;
599 ibit = fIndices[i] & 15;
600 indexnew[ibite] |= 1<<ibit;
601 }
602 } else {
603 for (i=0; i<kBlockSize; i++)
604 indexnew[i] = 65535;
605 for (i=0; i<fNPassed; i++){
606 ibite = fIndices[i]>>4;
607 ibit = fIndices[i] & 15;
608 indexnew[ibite] ^= 1<<ibit;
609 }
611 }
612 if (fIndices)
613 delete [] fIndices;
615 fType = 0;
616 fN = kBlockSize;
617 fPassing = true;
618 return;
619}
unsigned short UShort_t
Unsigned Short integer 2 bytes (unsigned short)
Definition RtypesCore.h:54
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t option
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 result
Used by TEntryList to store the entry numbers.
Int_t fLastIndexQueried
! to optimize GetEntry() in a loop
void OptimizeStorage()
If there are < kBlockSize or >kBlockSize*15 entries, change to an array representation.
UShort_t * fIndices
[fN]
bool Remove(Int_t entry)
Remove entry #entry If the block has already been optimized and the entries are stored as a list and ...
Int_t Next()
Return the next non-zero entry Faster than GetEntry() function.
TEntryListBlock & operator=(const TEntryListBlock &rhs)
Int_t fType
0 - bits, 1 - list
Int_t fNPassed
number of entries in the entry list (if fPassing=0 - number of entries not in the entry list
bool Enter(Int_t entry)
If the block has already been optimized and the entries are stored as a list and not as bits,...
bool fPassing
1 - stores entries that belong to the list 0 - stores entries that don't belong to the list
Int_t GetNPassed()
Returns the number of entries, passing the selection.
void Transform(bool dir, UShort_t *indexnew)
Transform the existing fIndices.
void PrintWithShift(Int_t shift) const
Print the indices of this block + shift (used from TEntryList::Print()) to print the current values.
~TEntryListBlock() override
Destructor.
Int_t fN
size of fIndices for I/O =fNPassed for list, fBlockSize for bits
Int_t fLastIndexReturned
! to optimize GetEntry() in a loop
UShort_t fCurrent
! to fasten Contains() in list mode
TEntryListBlock()
Default c-tor.
Int_t Contains(Int_t entry)
True if the block contains entry #entry.
Int_t GetEntry(Int_t entry)
Return entry #entry.
void Print(const Option_t *option="") const override
Print the entries in this block.
Int_t Merge(TEntryListBlock *block)
Merge with the other block Returns the resulting number of entries in the block.
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
Basic string class.
Definition TString.h:138
void ToUpper()
Change string to upper case.
Definition TString.cxx:1202
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:640