#include "TEntryListBlock.h"
#include "TString.h"
ClassImp(TEntryListBlock)
TEntryListBlock::TEntryListBlock()
{
fIndices = 0;
fN = kBlockSize;
fNPassed = 0;
fType = -1;
fPassing = 1;
fCurrent = 0;
fLastIndexReturned = -1;
fLastIndexQueried = -1;
}
TEntryListBlock::TEntryListBlock(const TEntryListBlock &eblock) : TObject(eblock)
{
Int_t i;
fN = eblock.fN;
if (eblock.fIndices){
fIndices = new UShort_t[fN];
for (i=0; i<fN; i++)
fIndices[i] = eblock.fIndices[i];
}
fNPassed = eblock.fNPassed;
fType = eblock.fType;
fPassing = eblock.fPassing;
fCurrent = eblock.fCurrent;
fLastIndexReturned = -1;
fLastIndexQueried = -1;
}
TEntryListBlock::~TEntryListBlock()
{
if (fIndices)
delete [] fIndices;
fIndices = 0;
}
Bool_t TEntryListBlock::Enter(Int_t entry)
{
if (entry > kBlockSize*16) {
Error("Enter", "illegal entry value!");
return 0;
}
if (!fIndices){
fIndices = new UShort_t[kBlockSize] ;
for (Int_t i=0; i<kBlockSize; i++)
fIndices[i] = 0;
fType = 0;
}
if (fType==0){
Int_t i = entry>>4;
Int_t j = entry & 15;
if ((fIndices[i] & (1<<j))==0){
fIndices[i] |= 1<<j;
fNPassed++;
return 1;
} else {
return 0;
}
}
UShort_t *bits = new UShort_t[kBlockSize];
Transform(1, bits);
Enter(entry);
return 0;
}
Bool_t TEntryListBlock::Remove(Int_t entry)
{
if (entry > kBlockSize*16) {
Error("Remove", "Illegal entry value!\n");
return 0;
}
if (fType==0){
Int_t i = entry>>4;
Int_t j = entry & 15;
if ((fIndices[i] & (1<<j))!=0){
fIndices[i] &= (0xFFFF^(1<<j));
fNPassed--;
return 1;
} else {
return 0;
}
}
UShort_t *bits = new UShort_t[kBlockSize];
Transform(1, bits);
return Remove(entry);
}
Int_t TEntryListBlock::Contains(Int_t entry)
{
if (entry > kBlockSize*16) {
Error("Contains", "Illegal entry value!\n");
return 0;
}
if (!fIndices && fPassing)
return 0;
if (fType==0){
Int_t i = entry>>4;
Int_t j = entry & 15;
Bool_t result = (fIndices[i] & (1<<j))!=0;
return result;
}
if (entry < fCurrent) fCurrent = 0;
if (fPassing){
for (Int_t i = fCurrent; i<fNPassed; i++){
if (fIndices[i]==entry){
fCurrent = i;
return kTRUE;
}
}
} else {
if (!fIndices || fNPassed==0){
return kTRUE;
}
if (entry > fIndices[fNPassed-1])
return kTRUE;
for (Int_t i= fCurrent; i<fNPassed; i++){
if (fIndices[i]==entry){
fCurrent = i;
return kFALSE;
}
if (fIndices[i]>entry){
fCurrent = i;
return kTRUE;
}
}
}
return 0;
}
Int_t TEntryListBlock::Merge(TEntryListBlock *block)
{
Int_t i, j;
if (block->GetNPassed() == 0) return GetNPassed();
if (GetNPassed() == 0){
fN = block->fN;
fIndices = new UShort_t[fN];
for (i=0; i<fN; i++)
fIndices[i] = block->fIndices[i];
fNPassed = block->fNPassed;
fType = block->fType;
fPassing = block->fPassing;
fCurrent = block->fCurrent;
fLastIndexReturned = -1;
fLastIndexQueried = -1;
return fNPassed;
}
if (fType==0){
if (block->fType == 0){
for (i=0; i<kBlockSize*16; i++){
if (block->Contains(i))
Enter(i);
}
} else {
if (block->fPassing){
for (i=0; i<block->fNPassed; i++){
Enter(block->fIndices[i]);
}
} else {
if (block->fNPassed==0){
for (i=0; i<kBlockSize*16; i++){
Enter(i);
}
}
for (j=0; j<block->fIndices[0]; j++)
Enter(j);
for (i=0; i<block->fNPassed-1; i++){
for (j=block->fIndices[i]+1; j<block->fIndices[i+1]; j++){
Enter(j);
}
}
for (j=block->fIndices[block->fNPassed-1]+1; j<kBlockSize*16; j++)
Enter(j);
}
}
} else {
if (GetNPassed() + block->GetNPassed() > kBlockSize){
UShort_t *bits = new UShort_t[kBlockSize];
Transform(1, bits);
Merge(block);
} else {
if (block->fType==1){
Int_t en = block->fNPassed;
Int_t newsize = fNPassed + en;
UShort_t *newlist = new UShort_t[newsize];
UShort_t *elst = block->fIndices;
Int_t newpos, elpos;
newpos = elpos = 0;
for (i=0; i<fNPassed; i++) {
while (elpos < en && fIndices[i] > elst[elpos]) {
newlist[newpos] = elst[elpos];
newpos++;
elpos++;
}
if (fIndices[i] == elst[elpos]) elpos++;
newlist[newpos] = fIndices[i];
newpos++;
}
while (elpos < en) {
newlist[newpos] = elst[elpos];
newpos++;
elpos++;
}
delete [] fIndices;
fIndices = newlist;
fNPassed = newpos;
fN = fNPassed;
} else {
Int_t en = block->fNPassed;
Int_t newsize = fNPassed + en;
UShort_t *newlist = new UShort_t[newsize];
Int_t newpos, current;
newpos = current = 0;
for (i=0; i<kBlockSize*16; i++){
if (!block->Contains(i)) continue;
while(current < fNPassed && fIndices[current]<i){
newlist[newpos] = fIndices[current];
current++;
newpos++;
}
if (fIndices[current]==i) current++;
newlist[newpos] = i;
newpos++;
}
while(current<fNPassed){
newlist[newpos] = fIndices[current];
newpos++;
current++;
}
delete [] fIndices;
fIndices = newlist;
fNPassed = newpos;
fN = fNPassed;
}
}
}
fLastIndexQueried = -1;
fLastIndexReturned = -1;
OptimizeStorage();
return GetNPassed();
}
Int_t TEntryListBlock::GetNPassed()
{
if (fPassing)
return fNPassed;
else
return kBlockSize*16-fNPassed;
}
Int_t TEntryListBlock::GetEntry(Int_t entry)
{
if (entry > kBlockSize*16) return -1;
if (entry > GetNPassed()) return -1;
if (entry == fLastIndexQueried+1) return Next();
else {
Int_t i=0; Int_t j=0; Int_t entries_found=0;
if (fType==0){
if ((fIndices[i] & (1<<j))!=0)
entries_found++;
while (entries_found<entry+1){
if (j==15){i++; j=0;}
else j++;
if ((fIndices[i] & (1<<j))!=0)
entries_found++;
}
fLastIndexQueried = entry;
fLastIndexReturned = i*16+j;
return fLastIndexReturned;
}
if (fType==1){
if (fPassing){
fLastIndexQueried = entry;
fLastIndexReturned = fIndices[entry];
return fIndices[entry];
} else {
fLastIndexQueried = entry;
if (!fIndices || fNPassed==0){
fLastIndexReturned = entry;
return fLastIndexReturned;
}
for (i=0; i<fIndices[0]; i++){
entries_found++;
if (entries_found==entry+1){
fLastIndexReturned = i;
return fLastIndexReturned;
}
}
for (i=0; i<fNPassed-1; i++){
for (j=fIndices[i]+1; j<fIndices[i+1]; j++){
entries_found++;
if (entries_found==entry+1){
fLastIndexReturned = j;
return fLastIndexReturned;
}
}
}
for (j=fIndices[fNPassed-1]+1; j<kBlockSize*16; j++){
entries_found++;
if (entries_found==entry+1){
fLastIndexReturned = j;
return fLastIndexReturned;
}
}
}
}
return -1;
}
}
Int_t TEntryListBlock::Next()
{
if (fLastIndexQueried==GetNPassed()-1){
fLastIndexQueried=-1;
fLastIndexReturned = -1;
return -1;
}
if (fType==0) {
Int_t i=0;
Int_t j=0;
fLastIndexReturned++;
i = fLastIndexReturned>>4;
j = fLastIndexReturned & 15;
Bool_t result=(fIndices[i] & (1<<j))!=0;
while (result==0){
if (j==15) {j=0; i++;}
else j++;
result = (fIndices[i] & (1<<j))!=0;
}
fLastIndexReturned = i*16+j;
fLastIndexQueried++;
return fLastIndexReturned;
}
if (fType==1) {
fLastIndexQueried++;
if (fPassing){
fLastIndexReturned = fIndices[fLastIndexQueried];
return fIndices[fLastIndexQueried];
} else {
fLastIndexReturned++;
while (!Contains(fLastIndexReturned)){
fLastIndexReturned++;
}
return fLastIndexReturned;
}
}
return -1;
}
void TEntryListBlock::Print(const Option_t *option) const
{
TString opt = option;
opt.ToUpper();
if (opt.Contains("A")) PrintWithShift(0);
}
void TEntryListBlock::PrintWithShift(Int_t shift) const
{
Int_t i;
if (fType==0){
Int_t ibit, ibite;
Bool_t result;
for (i=0; i<kBlockSize*16; i++){
ibite = i>>4;
ibit = i & 15;
result = (fIndices[ibite] & (1<<ibit))!=0;
if (result)
printf("%d\n", i+shift);
}
} else {
if (fPassing){
for (i=0; i<fNPassed; i++){
printf("%d\n", fIndices[i]+shift);
}
} else {
if (fNPassed==0){
for (i=0; i<kBlockSize*16; i++)
printf("%d\n", i+shift);
return;
}
for (i=0; i<fIndices[0]; i++){
printf("%d\n", i+shift);
}
for (i=0; i<fNPassed-1; i++){
for (Int_t j=fIndices[i]+1; j<fIndices[i+1]; j++){
printf("%d\n", j+shift);
}
}
for (Int_t j=fIndices[fNPassed-1]+1; j<kBlockSize*16; j++){
printf("%d\n", j+shift);
}
}
}
}
void TEntryListBlock::OptimizeStorage()
{
if (fType!=0) return;
if (fNPassed > kBlockSize*15)
fPassing = 0;
if (fNPassed<kBlockSize || !fPassing){
UShort_t *indexnew = new UShort_t[fNPassed];
Transform(0, indexnew);
}
}
void TEntryListBlock::Transform(Bool_t dir, UShort_t *indexnew)
{
Int_t i=0;
Int_t ilist = 0;
Int_t ibite, ibit;
if (!dir) {
for (i=0; i<kBlockSize*16; i++){
ibite = i >> 4;
ibit = i & 15;
Bool_t result = (fIndices[ibite] & (1<<ibit))!=0;
if (result && fPassing){
indexnew[ilist] = i;
ilist++;
}
else if (!result && !fPassing){
indexnew[ilist] = i;
ilist++;
}
}
if (fIndices)
delete [] fIndices;
fIndices = indexnew;
fType = 1;
if (!fPassing)
fNPassed = kBlockSize*16-fNPassed;
fN = fNPassed;
return;
}
if (fPassing){
for (i=0; i<kBlockSize; i++)
indexnew[i] = 0;
for (i=0; i<fNPassed; i++){
ibite = fIndices[i]>>4;
ibit = fIndices[i] & 15;
indexnew[ibite] |= 1<<ibit;
}
} else {
for (i=0; i<kBlockSize; i++)
indexnew[i] = 65535;
for (i=0; i<fNPassed; i++){
ibite = fIndices[i]>>4;
ibit = fIndices[i] & 15;
indexnew[ibite] ^= 1<<ibit;
}
fNPassed = kBlockSize*16-fNPassed;
}
if (fIndices)
delete [] fIndices;
fIndices = indexnew;
fType = 0;
fN = kBlockSize;
fPassing = 1;
return;
}