4 ///**************************************************************************
5 ///* This file is property of and copyright by the ALICE HLT Project *
6 ///* All rights reserved. *
8 ///* Primary Author: Jenny Wagner (jwagner@cern.ch) *
10 ///* Permission to use, copy, modify and distribute this software and its *
11 ///* documentation strictly for non-commercial purposes is hereby granted *
12 ///* without fee, provided that the above copyright notice appears in all *
13 ///* copies and that both the copyright notice and this permission notice *
14 ///* appear in the supporting documentation. The authors make no claims *
15 ///* about the suitability of this software for any purpose. It is *
16 ///* provided "as is" without express or implied warranty. *
17 ///**************************************************************************
19 /// @file AliHLTCOMPHuffmanAltro.cxx
20 /// @author Jenny Wagner
22 /// @brief The Huffman compressor
25 #include "AliHLTCOMPHuffmanAltro.h"
26 #include "AliRawReaderMemory.h"
27 #include "AliAltroRawStreamV3.h"
35 using std::accumulate;
39 // Helper class for std::accumulate algorithm.
40 class AliHLTCOMPHuffmanOccurrenceSum {
42 typedef int first_argument_type;
43 typedef AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct second_argument_type;
44 typedef bool result_type;
45 int operator() (int a, AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct b) {
46 return a+b.fabundance;
51 /** ROOT macro for the implementation of ROOT specific class methods */
52 ClassImp(AliHLTCOMPHuffmanAltro)
54 AliHLTCOMPHuffmanAltro::AliHLTCOMPHuffmanAltro()
55 : TObject(), AliHLTLogging()
57 , fpAltroRawStream(NULL)
59 , fCompressionSwitch(0)
60 , fPointer2InData(NULL)
61 , fPointer2OutData(NULL)
64 , fNrcuTrailerwords(0)
67 , fTrainingTable(NULL)
68 , fTranslationTable(NULL)
70 // standard constructor
73 AliHLTCOMPHuffmanAltro::AliHLTCOMPHuffmanAltro(Bool_t compressionswitch, Bool_t trainingmode, AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct* translationtable, Int_t nrcutrailerwords)
74 : TObject(), AliHLTLogging()
76 , fpAltroRawStream(NULL)
77 , fTrainingMode(trainingmode)
78 , fCompressionSwitch(compressionswitch)
79 , fPointer2InData(NULL)
80 , fPointer2OutData(NULL)
83 , fNrcuTrailerwords(nrcutrailerwords)
86 , fTrainingTable(NULL)
87 , fTranslationTable(translationtable)
92 AliHLTCOMPHuffmanAltro::~AliHLTCOMPHuffmanAltro()
95 if (fpAltroRawStream) delete fpAltroRawStream;
96 fpAltroRawStream=NULL;
97 if (fpRawReader) delete fpRawReader;
100 if (fTrainingTable) delete [] fTrainingTable;
104 int AliHLTCOMPHuffmanAltro::AddInputData(UChar_t* memory, ULong_t datasize, Int_t equipmentId)
106 /// SetInputData takes input data pointer and input data size from component class
107 if (memory == NULL) {
111 // check datasize < header + trailer
112 if (datasize <= 32 + fNrcuTrailerwords) { // 8*32 (headerwords) = 8* 4*8 (headerbytes)
113 HLTError("Error! Size of input data less than header and trailer");
117 // FIXME: fPointer2InData is obsolete
118 fPointer2InData = (AliHLTUInt8_t*)memory;
119 fInputDataSize = datasize; // size in bytes
122 std::auto_ptr<AliRawReaderMemory> rawReader(new AliRawReaderMemory);
123 std::auto_ptr<AliAltroRawStreamV3> rawStream(new AliAltroRawStreamV3(rawReader.get()));
125 if (!rawReader.get() || !rawStream.get()) {
129 fpRawReader=rawReader.release();
130 fpAltroRawStream=rawStream.release();
133 fpRawReader->AddBuffer(memory, datasize, equipmentId);
138 int AliHLTCOMPHuffmanAltro::Reset()
140 /// Reset and prepare for new event
142 fpRawReader->ClearBuffers();
144 if (fpAltroRawStream) {
145 fpAltroRawStream->Reset();
148 InitNewTrainingTable();
153 int AliHLTCOMPHuffmanAltro::SetOutputData(AliHLTUInt8_t* outputdata, unsigned long outputsize)
155 /// SetOuptputData takes output data pointer and outputsize from component class
156 if (outputdata == NULL) {
160 fPointer2OutData = (AliHLTUInt64_t*) outputdata;
161 fOutputDataSize = outputsize;
163 // errors: compression: when outputdatasize < inputdatasize
164 // decompress.: when outputdatasize < inputMultiplier * inputdatasize
165 // this should not happen with current config in component (inputMultiplier = 4.0 for decomp and 1.0 for comp)
166 if (fCompressionSwitch) { // compression
167 if(outputsize < fInputDataSize) {
168 HLTError("Error! Size of output data not equal to size of input data for compression: reserved memory space might be too small");
171 } else { // decompression
172 if(outputsize < (fInputDataSize << 1)) { // smaller than inputdatasize * 2 not possible
173 HLTError("Error! Size of output data too small for decompression");
181 unsigned long AliHLTCOMPHuffmanAltro::GetOutputDataSize()
183 // GetOutputDataSize delivers output data size for component class to arrange blocks for output writing
184 // error when fOuputDataSize = 0; (not by training as there is no output when training)
185 if((fOutputDataSize == 0) && (fTrainingMode == kFALSE)) {
186 HLTError("Error! Calculated output data size is zero");
189 return fOutputDataSize;
192 int AliHLTCOMPHuffmanAltro::InitNewTrainingTable()
194 // Initialise training table
195 if (!fTrainingTable) fTrainingTable = new AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct[TIMEBINS];
196 if (!fTrainingTable) return -ENOMEM;
198 //initialise this array:
199 for(Int_t ii = 0; ii < TIMEBINS; ii++) {
200 fTrainingTable[ii].famplitude = ii;
201 fTrainingTable[ii].fabundance = 0;
202 fTrainingTable[ii].fcode = 2; //to assure that each leaf is assigned either 0 or 1!!!
208 int AliHLTCOMPHuffmanAltro::SetHuffmanData(AliHLTCOMPHuffmanData* huffmandata) const
210 // write produced code and occurrence table to Huffman Data
211 return huffmandata->InitHuffmanData(fTrainingTable, fTranslationTable);
214 int AliHLTCOMPHuffmanAltro::GetTrainingTable(const AliHLTCOMPHuffmanData* huffmandata)
216 // take translation table from HuffmanData
217 huffmandata->GetOccurrenceTable(fTrainingTable);
218 if (fVerbosity>0) Print("trainingtable");
223 int AliHLTCOMPHuffmanAltro::GetTranslationTable(const AliHLTCOMPHuffmanData* huffmandata)
225 // initialise fTranslationTable
226 if (fTranslationTable) delete fTranslationTable;
227 fTranslationTable = new AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct[TIMEBINS];
228 if (!fTranslationTable) return -ENOMEM;
230 for(Int_t kk = 0; kk < TIMEBINS; kk++) {
231 fTranslationTable[kk].famplitude = 0;
232 fTranslationTable[kk].fhuffmancode = 0;
233 fTranslationTable[kk].fvalidcodelength = 0;
236 // take translation table from HuffmanData
237 huffmandata->GetCodeTable(fTranslationTable);
238 if (fVerbosity>0) Print("translationtable");
243 /** ProcessData function to process data compression or decompression */
244 void AliHLTCOMPHuffmanAltro::ProcessData()
246 // see header file for class documentation
247 // set mode to process:
248 if(fCompressionSwitch == kTRUE && fTrainingMode == kFALSE) // encoding without training
250 EntropyCompression();
252 // information about compression ratio
253 HLTDebug("original filesize (bytes) = %d", fInputDataSize);
254 HLTDebug("compressed filesize (bytes) = %d", fOutputDataSize);
255 HLTDebug("compression ratio after Huffman encoding is %f", ((Double_t) fOutputDataSize)/fInputDataSize);
259 if(fCompressionSwitch == kTRUE && fTrainingMode == kTRUE) // encoding with training
263 // information about calculated entropy (contained in GetEntropy()) and compression ratio
267 else // decoding (no training possible, which is checked for errors by component)
269 EntropyDecompression();
271 // information about compression ratio
272 HLTDebug("compressed filesize (bytes) = %d", fInputDataSize);
273 HLTDebug("filesize after decoding (bytes) = %d", fOutputDataSize);
274 HLTDebug("compression ratio calculated from Huffman decompressing has been %f",((Double_t) fInputDataSize)/fOutputDataSize);
279 Double_t AliHLTCOMPHuffmanAltro::GetEntropy()
281 // Information about calculated entropy
282 if (fVerbosity>0) HLTInfo("Calculated entropy = %f",fEntropy);
287 /** Compression: take raw input data, code table and put out entropy encoded data */
288 Int_t AliHLTCOMPHuffmanAltro::EntropyCompression()
290 // see header file for class documentation
291 // initialise input and output pointers
292 AliHLTUInt32_t* pointer2InData = (AliHLTUInt32_t*) fPointer2InData;
293 AliHLTUInt64_t* pointeroutputprop = fPointer2OutData;
295 //first output word has to be initialised
296 pointeroutputprop[0] = 0;
298 // initialise output size
301 // initialise required variables for input reading
302 AliHLTUInt32_t data10 = 0; // temporary number to read out 10bit word
303 UInt_t idxwd = 8; // counts lines in input array (start after 8 x 32 bits header words)
304 UInt_t idx10 = 0; // counts 10-bits words
305 UInt_t bitpswd = 0; // counts current bitposition in idxwd
307 // number of 32-bits trailer and 32-bits common data header words:
308 // (taken out of compression!)
309 // UInt_t fNrcuTrailerwords = 1; // determined by user input as argument
310 UInt_t headerwords = 8;
312 // initialise required variables for ouput creation:
313 UInt_t idxoutwd = headerwords >> 1; // counts lines in output array (start after header words)
314 UInt_t bitpsoutwd = 0; // counts current bitposition in idxoutwd
316 // validation test variables:
317 // Int_t bitcounter = 0; // additional test for number of read in 10 bit words
318 // Int_t sumlength = 0; // additional test for length of encoded file
320 // error and abort when total number of bits cannot be divided by 32:
321 // remember that fInputDataSize is given in BYTES!
322 if (((fInputDataSize << 3) & 0x1F) != 0)
324 HLTError("Error! Input data size (bytes) %i cannot be divided into 32 bit words", fInputDataSize);
329 // error and abort when input data without trailer words cannot be divided into 10 bit words:
330 if ((( (fInputDataSize << 3) - (fNrcuTrailerwords << 5) - (headerwords << 5)) % 10) != 0)
332 HLTError("Error! Input data (bytes) %i without trailer (bytes) %i and header words (bytes) %i cannot be divided into 10 bit words", fInputDataSize, (fNrcuTrailerwords << 2),(headerwords << 2));
337 // last line of 32-bits which is to be encoded
338 UInt_t endNdx = (fInputDataSize>>2)-fNrcuTrailerwords;
340 // write header to output (two 32-bits words input header in one 64-bits word output header):
342 UInt_t headwordcntr = 0;
344 while(headcntr != (headerwords >> 1))
346 // write first header word to the left
347 pointeroutputprop[headcntr] = ((AliHLTUInt64_t) pointer2InData[headwordcntr]);
349 // write second header word to the right
350 pointeroutputprop[headcntr] |= ( ((AliHLTUInt64_t) pointer2InData[headwordcntr+1]) << 32);
352 // goto next header line and next two header words
357 // EntropyCompression() for 10-bit values of ALTRO-Blocks:
358 while (idxwd < endNdx)
360 // write input data in data10 and cut out 10 bits with mask 0x3FFU = 0011 1111 1111
361 data10 = (pointer2InData[idxwd] >> bitpswd ) & 0x3FFU;
364 // cout << "10 bit data cut out from data10 = " << data10 << endl;
366 // if number of bits left in read input less than 10, get remaining bits from next 32-bits word
370 // cout << "adding bits from next word at bit position " << bitpswd << endl;
372 data10 |= (pointer2InData[idxwd + 1]) << (32 - bitpswd);
376 // cout << "complete 10-bits word = << data10 << endl;
380 // print first 100 10-bits words with resp.code and validcodelength to screen...
383 // cout << "read 10-bits word (HEX) = " << hex << data10 << dec <<" with code (DEC) = " << fTranslationTable[data10].fhuffmancode << " and validcodelength (DEC) = " << fTranslationTable[data10].fvalidcodelength << endl;
386 // start encoding of codes with less than 65 bits codelength
387 if(fTranslationTable[data10].fvalidcodelength < 65)
389 // error and abortion when validcodelength = 0
390 if (fTranslationTable[data10].fvalidcodelength == 0)
392 HLTError("Error! Valid codelength of read 10 bit word (DEC) %i is zero", data10);
399 // sumlength += fTranslationTable[data10].fvalidcodelength;
401 if(fTranslationTable[data10].fvalidcodelength + bitpsoutwd < 64) //if new code fits in current output line
404 // cout << "writing code (HEX) = " << hex << fTranslationTable[data10].fhuffmancode << dec << " to line (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
406 // shift line to right
407 pointeroutputprop[idxoutwd] <<= fTranslationTable[data10].fvalidcodelength;
409 // append code at left side of line
410 pointeroutputprop[idxoutwd] |= fTranslationTable[data10].fhuffmancode;
413 // cout << "code written and current line updated to (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
415 else //if not, write lowest bits to next line
418 // cout << "writing bits of code (HEX) = " << hex << fTranslationTable[data10].fhuffmancode << dec << " to line (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
420 // create temporary variable for performance gain:
421 Int_t restcode = fTranslationTable[data10].fvalidcodelength - 64 + bitpsoutwd;
423 // shift line completely to the right
424 pointeroutputprop[idxoutwd] <<= (64 - bitpsoutwd);
426 // append upper bits of code to this line
427 pointeroutputprop[idxoutwd] |= (fTranslationTable[data10].fhuffmancode >> (restcode));
430 // cout << "code bits written and current line updated to (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
432 // write lowest code bits to next line
436 // trick to cut out already written bits from code
437 AliHLTUInt64_t tempbuffer = fTranslationTable[data10].fhuffmancode;
438 tempbuffer <<= 64-bitpsoutwd; // shift away written code
439 tempbuffer >>= 64-bitpsoutwd; // shift back to get lowest bits
441 pointeroutputprop[idxoutwd] = tempbuffer;
444 // cout << "code bits written and next line started as (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
447 else // if code is longer than 64 bits: use *morecode (not tested therefore left away)
449 HLTError("Error! Huffman Code Table does not contain codes with valid codelength longer than 64 bits");
456 // cout << " current positions:" << endl;
457 // cout << "input : idxwd (DEC) = " << idxwd << " bitpswd (DEC) = " << bitpswd << " idx10 (DEC) = " << idx10 << endl;
458 // cout << "output : idxoutwd (DEC) = " << idxoutwd << " bitpsoutwd (DEC) = " << bitpsoutwd << endl;
460 // calculate new positions
461 bitpsoutwd = (fTranslationTable[data10].fvalidcodelength + bitpsoutwd) & 0x3F;
463 ++idx10; // go on reading 10 bit word
465 // bit position word reads position in 32bit word when 10 bits are read out
466 bitpswd = (idx10 * 10) & 0x1F;
468 // index word reads position of 32bit word in input array
469 idxwd = ((idx10 * 10)>>5)+8;
472 //if(idxoutwd > 2635)
474 // cout << " encoding value (HEX) = " << hex << data10 << dec << endl;
475 // cout << " code (HEX) = " << hex << fTranslationTable[data10].fhuffmancode << dec << endl;
476 // cout << " valid code length (DEC) = " << fTranslationTable[data10].fvalidcodelength << endl;
477 // cout << " new positions:" << endl;
478 // cout << "input : idxwd (DEC) = " << idxwd << " bitpswd (DEC) = " << bitpswd << " idx10 (DEC) = " << idx10 << endl;
479 // cout << "output : idxoutwd (DEC) = " << idxoutwd << " bitpsoutwd (DEC) = " << bitpsoutwd << endl;
482 }// end of encoding (while loop)
484 // if new line is already started
492 // fill rest of line with zeroes
493 pointeroutputprop[idxoutwd] <<= (64 - bitpsoutwd);
496 // next 32 bits are to memorise first bitposition after the code
497 UInt_t lastvalidbitps = bitpsoutwd;
500 // cout << "last bitpsoutwd = lastvalidbitps (DEC) = " << bitpsoutwd << endl;
503 // cout << "second last code line (HEX) = " << hex << pointeroutputprop[idxoutwd-1] << dec << endl;
504 // cout << "last code line (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
505 // cout << "idxoutwd (DEC) = " << idxoutwd << endl;
507 // start new line and write last valid bit position and trailer words there:
511 pointeroutputprop[idxoutwd] = lastvalidbitps;
514 // cout << "first trailer line with lastvalidbitps (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
515 // cout << "idxoutwd (DEC) = " << idxoutwd << endl;
517 // write first trailerword
519 pointeroutputprop[idxoutwd] <<= 32;
520 pointeroutputprop[idxoutwd] |= pointer2InData[endNdx];
523 // cout << "first trailer line with lastvalidbitpos and first trailerword (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
525 if(fNrcuTrailerwords > 1) // if there is more than one trailerword
530 pointeroutputprop[idxoutwd] = pointer2InData[endNdx + 1]; // write second
533 // cout << "last trailer line with second trailerword (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
534 // cout << "idxoutwd (DEC) = " << idxoutwd << endl;
536 if (fNrcuTrailerwords == 3) // write third
540 pointeroutputprop[idxoutwd] <<= 32;
541 pointeroutputprop[idxoutwd] |= pointer2InData[endNdx +2];
544 // cout << "last trailer line with last trailerword (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
549 // cout << "file ended at current positions:" << endl;
550 // cout << "input : idxwd (DEC) = " << idxwd << " bitpswd (DEC) = " << bitpswd << " idx10 (DEC) = " << idx10 << endl;
551 // cout << "output : idxoutwd (DEC) = " << idxoutwd << " bitpsoutwd (DEC) = " << bitpsoutwd << endl;
552 // cout << "current output line (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
553 // cout << "sum of codelengths (DEC) = " << sumlength << endl;
554 // cout << "number of read 10 bit data (DEC) = " << bitcounter << endl;
555 // cout << "first input trailer (HEX) = " << hex << pointer2InData[endNdx] << dec << endl;
557 // set fOutputDataSize in byte:
558 // idxoutwd*8 = number of whole 64 bits words in byte
559 // bitpsoutwd/8 = number of wohle 8 bits words within last idxoutwd
560 fOutputDataSize = (Int_t) ((idxoutwd << 3) + (bitpsoutwd >> 3));
562 // error and abortion when output data size for encoding is larger than input data size
563 if(fOutputDataSize > fInputDataSize)
565 HLTError("Error! Calculated data size for compressed output stream is larger than input data size");
571 // cout << "output data size (DEC) = " << fOutputDataSize << endl;
576 /** Mergesort used by TrainingData to sort an array with n entries from high abundance to low abundance */
577 AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct* AliHLTCOMPHuffmanAltro::Mergesort(AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct *unsortedarray, Int_t n)
579 // see header file for class documentation
580 //divide array into two halfs: left and right (fleft.size = divlength)
581 Int_t divlength = n >> 1;
585 // error when unsorted array = NULL
586 if (unsortedarray == NULL)
588 HLTError("Error! Pointer to final merge sorted abundance array = NULL");
591 return unsortedarray;
595 // sort both halfs recursively:
596 Mergesort(unsortedarray, divlength); //left half
597 Mergesort(&unsortedarray[divlength], n-divlength); //right half
600 // create temporary result array:
601 AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct* temp = new AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct[n];
606 // if left and right halves both have elements: chose the smaller one:
607 for (ii = 0, jj = divlength, kk = 0; ii < divlength && jj < n;)
609 if (unsortedarray[ii].fabundance > unsortedarray[jj].fabundance)
611 temp[kk] = unsortedarray[ii];
616 temp[kk] = unsortedarray[jj];
624 // if one half is empty take elements of the other one:
625 while (ii < divlength)
627 temp[kk] = unsortedarray[ii];
634 temp[kk] = unsortedarray[jj];
639 // copy sorted temp array back into original data array
640 for (Int_t ll = 0; ll < n; ll++)
642 unsortedarray[ll] = temp[ll];
648 // return pointer to original data array (which is sorted now)
649 return unsortedarray;
653 /** CreateHuffmanTree used by TrainingData to create the binary Huffman tree */
654 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* AliHLTCOMPHuffmanAltro::CreateHuffmanTree(AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* listroot,AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* lastelement, Int_t n)
656 // see header file for class documentation
657 // initialise pointer to go through list
658 //AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* nextpointer = listroot; // pointer for validation test below
659 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* lastpointer = lastelement;
661 // build Huffman tree while there are still elements in the list
665 // cout << "current number of remaining list elements n (DEC) = " << n << endl;
666 // cout << "current abundance of last list element (DEC) = " << lastpointer->fleafcontents.fabundance << endl;
667 // cout << "print all list elements from high to low to screen:" << endl;
668 // while(nextpointer != NULL)
670 // cout << nextpointer->fleafcontents.fabundance << endl;
671 // nextpointer = nextpointer->fnext;
673 // cout << " end of list " << endl;
675 // create new tree element from last two entries in orderedarray
676 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* temptree = new AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct;
677 // error if temptree = NULL
678 if (temptree == NULL)
680 HLTError("Error! Allocation of Huffman binary tree failed");
684 // initialise the new element:
685 temptree->fleafcontents.famplitude = TIMEBINS; //internal nodes mustn't be confused with real amplitudes (from 0 to bitsize)!
688 // cout <<"current abundance of last list element (DEC) = " << lastpointer->fleafcontents.fabundance << endl;
690 // initialise abundance starting with last element
691 temptree->fleafcontents.fabundance = lastpointer->fleafcontents.fabundance;
693 // code assignment small ones get 0, large ones get 1:
694 lastpointer->fleafcontents.fcode = 0;
696 // append smallest element on the left and set pointer temptree = parent
697 temptree->fleft = lastpointer;
698 lastpointer->fparent = temptree;
700 // go on to second last element and set abundance, code and append on right side of the new element
701 lastpointer = lastpointer->fprevious;
704 // cout << "current abundance of second last list element (DEC) = " << lastpointer->fleafcontents.fabundance << endl;
708 temptree->fleafcontents.fabundance += lastpointer->fleafcontents.fabundance;
709 lastpointer->fleafcontents.fcode = 1;
710 temptree->fright = lastpointer;
711 lastpointer->fparent = temptree;
713 temptree->fnext = NULL;
714 temptree->fprevious = NULL;
715 temptree->fparent = NULL;
718 // cout << "current abundance of temptree element = sum of leaf abundances (DEC) = " << temptree->fleafcontents.fabundance << endl;
720 // write temptree at the suitable place according to its abundance in the list
721 // initialise searchpointer to go through list
722 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* search = listroot;
723 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* sorting = listroot; // pointer from previous element
725 // check if listroot[0].fleafcontents.fabundance < temptree.fleafcontents.fabundance,
726 // if so, make temptree new root of list
727 if (temptree->fleafcontents.fabundance > listroot[0].fleafcontents.fabundance)
730 // cout << "abundance of new element (DEC) = " << temptree->fleafcontents.fabundance << " is larger than root abundance (DEC) = " << listroot[0].fleafcontents.fabundance << endl;
733 temptree->fnext = search;
734 search->fprevious = temptree;
735 //temptree->fprevious = NULL // for first list element is already done!
738 else //sort in at the suitable point in the list
740 search = listroot->fnext; // go one further than listroot!
742 while(search != NULL)
745 // cout << "current abundance of searchpointer (DEC) = " << searchpointer->fleafcontents.fabundance << endl;
747 // if abundance of list entry > abundance of new element, go to next element,
748 // else sort in at that point
749 if(search->fleafcontents.fabundance > temptree->fleafcontents.fabundance)
752 // cout << "abundance of searchpointer (DEC) = " << search->fleafcontents.fabundance << " is larger than temptree abundance (DEC) = " << temptree->fleafcontents.fabundance << endl;
754 sorting = search; // remember previous element
755 search = sorting->fnext; // goto next element
759 sorting->fnext = temptree; //insert temptree to previous
760 search->fprevious = temptree; //insert temptree to next
761 temptree->fprevious = sorting; // insert temptree to previous
762 temptree->fnext = search; //insert temptree to next
764 search = NULL; //stop sorting in
767 } //end of sorting in
769 // cut the two elements out of the list:
771 lastpointer = lastpointer->fprevious;
772 lastpointer->fnext = NULL;
775 // cout << "cutting out last two list elements, abundance of current last list element is (DEC) = " << lastpointer->fleafcontents.fabundance << endl;
782 // cout << "current list with new (temptree) element sorted in:" << endl;
784 // AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct * showpointer = listroot;
785 // while((showpointer->fnext != NULL) && (showpointer->fleafcontents.fabundance != 0))
787 // cout << "amplitude (DEC) = " << showpointer->fleafcontents.famplitude << " abundance (DEC) = " << showpointer->fleafcontents.fabundance << endl;
789 // showpointer = showpointer->fnext;
792 // cout << "amplitude (DEC) = " << showpointer->fleafcontents.famplitude << " abundance (DEC) = " << showpointer->fleafcontents.fabundance << endl;
795 // perform createHuffmanTree with n-1 elements:
799 // termination for n = 2:
801 // create new tree element from last two entries
802 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* temptree = new AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct;
803 // error if temptree = NULL
804 if (temptree == NULL)
806 HLTError("Error! Pointer to root of Huffman binary tree = NULL");
810 // initialise the new element:
811 temptree->fleafcontents.famplitude = TIMEBINS; //internal nodes mustn't be confused with real event names (from 0 to TIMEBINS)!
814 // cout << "assemble last two elements to final tree:" << endl;
815 // cout << "abundance of last list element (DEC) = " << lastpointer->fleafcontents.fabundance << endl;
817 // initialise abundance starting with last element
818 temptree->fleafcontents.fabundance = lastpointer->fleafcontents.fabundance;
820 // code assignment small ones get 0, large ones get 1:
821 lastpointer->fleafcontents.fcode = 0;
823 // append smallest element on the left:
824 temptree->fleft = lastpointer;
825 lastpointer->fparent = temptree;
828 // cout << "abundance of first list element (DEC) = " << listroot->fleafcontents.fabundance << endl;
832 // go on to second last element and set abundance, code and append on right side of the new element
833 temptree->fleafcontents.fabundance +=listroot->fleafcontents.fabundance;
834 listroot->fleafcontents.fcode = 1;
835 temptree->fright = listroot;
836 listroot->fparent = temptree;
838 temptree->fnext = NULL;
839 temptree->fprevious = NULL;
840 temptree->fparent = NULL;
843 // cout << " final abundance of tree root (DEC) = " << temptree->fleafcontents.fabundance << endl;
848 /** HuffmanCode used by TrainingData to create the Huffman code for all leaves of the HuffmanTree */
849 Int_t AliHLTCOMPHuffmanAltro::HuffmanCode(AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* treeroot, AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct* HuffmanCodearray)
851 // see header file for class documentation
852 while ((treeroot->fleft != NULL) || (treeroot->fright != NULL))
854 // define pointer to go through tree
855 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* finder = treeroot;
857 // define temporary HuffmanCode struct to sort into the Huffmanarray later
858 // array necessary for codelengths > 64 bits
859 Int_t tempstructsize = (Int_t) ceil((double) TIMEBINS/64); // maximal codelength: TIMEBINS
861 AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct* tempstruct = new AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct[tempstructsize];
862 if (!tempstruct) return -1;
864 for(Int_t jj = 0; jj < tempstructsize; jj++)
866 tempstruct[jj].fhuffmancode = 0;
869 Int_t passednodes = 0;
871 // start searching for leaves
874 // if finder points at a leaf:
875 if (finder->fright == NULL && finder->fleft == NULL)
877 //if it is an internal node
878 if(finder->fleafcontents.famplitude == TIMEBINS)
881 // cout << "found internal node with following abundance to delete (DEC) = " << finder->fleafcontents.fabundance << endl;
883 //go back to parent and delete node with 256
884 if (finder->fleafcontents.fcode == 0) // node was left one
886 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* parent = finder->fparent;
887 parent->fleft = NULL;
889 else // node was right one
891 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* parent = finder->fparent;
892 parent->fright = NULL;
897 else // if it is a leaf
899 Int_t checkright = 0; // so leaf is left children
901 // leaf can also be a right leaf:
902 if (finder->fleafcontents.fcode == 1)
904 checkright = 1; // if code == 1, leaf is right children
907 // write collected data in the respective array:
909 // validation test if amplitudes are correctly found (after being initialised to TIMEBINS+1 in TrainingData()
910 // HuffmanCodearray[finder->fleafcontents.famplitude].famplitude = finder->fleafcontents.famplitude;
913 // cout << "found leaf with amplitude (DEC) = " << finder->fleafcontents.famplitude << endl;
915 HuffmanCodearray[finder->fleafcontents.famplitude].fvalidcodelength = passednodes;
918 // cout << "found leaf with validlength (DEC) = " << HuffmanCodearray[foundleaves].fvalidcodelength << endl;
921 HuffmanCodearray[finder->fleafcontents.famplitude].fhuffmancode = tempstruct[0].fhuffmancode;
924 //cout << "found leaf with code (HEX) = " << hex << HuffmanCodearray[finder->fleafcontents.famplitude].fhuffmancode << dec << endl;
926 if(passednodes > 64) // if there is more code to write (not usual in normal zero-suppressed data streams!)
929 HLTError("Error! Valid codelength for datum (DEC) %d is larger than 64 bits, which is not usual for normal input data", finder->fleafcontents.famplitude);
936 // cout << "found leaf written after passed nodes (DEC) = " << passednodes << endl;
938 // deleting found leaf from tree
939 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* parent = finder->fparent; // go one up and set pointer to leaf to zero:
942 // cout << "parent abundance from found leaf (DEC) = " << finder->fleafcontents.fabundance << endl;
944 if (checkright == 1) // if leaf is right children -> delete right
946 parent->fright = NULL;
948 else //else: delete fleft
950 parent->fleft = NULL;
956 // cout << " finder pointer at end of deleting the found leaf (DEC) = " << finder << endl;
958 else // if node is not a leaf
961 //cout << "finder pointer to left child (DEC) = " << finder->fleft << endl;
962 //cout << "finder pointer to right child (DEC) = " << finder->fright << endl;
964 if(finder->fleft != NULL)
966 finder = finder->fleft; // pointer to children
969 //cout << "left child has abundance (DEC) = " << finder->fleafcontents.fabundance << endl;
971 // shift left to arrange space for new code element which is zero (->left!)
972 // i.e. nothing further needed to create code
975 //cout << "code for left child is created as (DEC) = " << tempstruct->fhuffmancode << endl;
977 //problem if passednodes > 63 --> inserting another bit becomes tricky:
980 tempstruct[0].fhuffmancode = tempstruct[0].fhuffmancode << 1;
982 else // error as valid codelength should not exceed 64 bits
985 HLTError("Error! Valid codelength for current encoding process becomes larger than 64 bits, which is not usual for normal input data");
992 //cout << "code for left child has been written as (DEC) = " << tempstruct->fhuffmancode << endl;
998 finder = finder->fright; // goto right children
1001 //cout << "right child has abundance (DEC) = " << finder->fleafcontents.fabundance << endl;
1003 // shift left to arrange space for new code element which is one (->right!)
1004 // i.e. append 1 at the right end of the code via OR-function
1007 //cout << "code for right child is created as (DEC) = " << tempstruct->fhuffmancode << endl;
1009 //problem if passednodes > 63 --> inserting another bit becomes tricky:
1010 if(passednodes < 64)
1012 tempstruct[0].fhuffmancode = tempstruct[0].fhuffmancode << 1;
1013 tempstruct[0].fhuffmancode = (tempstruct[0].fhuffmancode) | 1;
1018 HLTError("Error! Valid codelength for current encoding process becomes larger than 64 bits, which is not usual for normal input data");
1023 //cout << "code for right children has been written as (DEC) = " << tempstruct->fhuffmancode << endl;
1026 } // end of right children search
1027 } // end of no-leaf-search
1028 } // end of while-loop for leaf-search
1031 delete[] tempstruct;
1032 } // end of while-loop for tree != root only
1034 // error when there is an amplitude = TIMEBINS in the HuffmanArray
1035 for(int jj = 0; jj < TIMEBINS; jj++)
1037 if(HuffmanCodearray[jj].famplitude == TIMEBINS)
1039 HLTError("Error! Internal node from Huffman tree in Huffmanarray for 10 bit word (DEC) %i", jj);
1046 Int_t AliHLTCOMPHuffmanAltro::TrainingData()
1048 // fill training data to create the HuffmanCode from a binary tree
1051 // total number of events counted
1052 Int_t totalnumber = 0;
1054 if (!fpAltroRawStream) return -ENODATA;
1055 fpAltroRawStream->Reset();
1057 // initialise required variables for input reading:
1058 AliHLTUInt32_t data10 = 0; // temporary number to read out 10bit word with
1060 if (!fTrainingTable && (iResult=InitNewTrainingTable())<=0)
1064 while (fpAltroRawStream->NextDDL()) {
1065 while (fpAltroRawStream->NextChannel()) {
1067 // include payload size in training table
1068 data10=fpAltroRawStream->GetChannelPayloadSize();
1069 //fTrainingTable[(Int_t)(data10)].fabundance += 1;
1070 if (fpAltroRawStream->NextBunch()) {
1072 // include bunch length in training table
1073 int iBunchLen=fpAltroRawStream->GetBunchLength();
1075 fTrainingTable[(Int_t)(data10)].fabundance += 1;
1077 // include start time in training table
1078 int iStartTime=fpAltroRawStream->GetStartTimeBin();
1080 //fTrainingTable[(Int_t)(data10)].fabundance += 1;
1082 const UShort_t* signals=fpAltroRawStream->GetSignals();
1083 for (int sigpos=0; sigpos<iBunchLen-2; sigpos++) {
1084 data10=signals[sigpos];
1085 // include signals in training table
1086 fTrainingTable[(Int_t)(data10)].fabundance += 1;
1089 } while (fpAltroRawStream->NextBunch());
1092 // increase total number of events
1097 fOutputDataSize = 0;
1102 /** Create Huffman code table out of abundance table filled by training data in DoEvent function of component */
1103 Int_t AliHLTCOMPHuffmanAltro::CreateCodeTable()
1105 // see header file for class documentation
1106 // using merge sort to sort the list: (stable algorithm, quick even in worst case O(nlogn))
1107 AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct* HuffmanArraySorted = Mergesort(fTrainingTable, TIMEBINS);
1109 // abort when there is no pointer to sorted array (error produced in Mergesort function)
1110 if(HuffmanArraySorted == NULL)
1115 // error and abort if list not properly sorted:
1116 // go through list and watch if current abundance of HuffmanData is always larger than next element
1117 for(int kk = 0; kk < TIMEBINS - 1; kk++)
1119 if(HuffmanArraySorted[kk].fabundance < HuffmanArraySorted[kk+1].fabundance)
1121 HLTError("Error! List of 10 bit word abundances not properly sorted by merge sort", "Element with 10 bit word (DEC) %i has abundance %i which is smaller than element with 10 bit word (DEC) %i with abundance %i",HuffmanArraySorted[kk].famplitude, HuffmanArraySorted[kk].fabundance, HuffmanArraySorted[kk+1].famplitude, HuffmanArraySorted[kk+1].fabundance);
1128 //cout << "merge sort for training table is now done " << endl;
1130 // after mergesorting, zero arrays are last ones in array with abundance = 0
1131 // -> count filled array entries
1132 UInt_t filled = TIMEBINS; // to ensure that every amplitude (no matter if it appears in training or not) gets a code
1133 UInt_t zeroentries = 0; // number of non used 10 bit words (with abundance = 0)
1135 // check how many 10 bit words are used ("missing channel problem)
1136 for(UInt_t kk = 0; kk < TIMEBINS; kk++)
1138 if((HuffmanArraySorted[kk].fabundance == 0))
1144 // -> new array size is "filled"
1146 // cout << "number of filled array entries (DEC) = " << filled << endl;
1148 // warning when there are a lot of non used 10 bit words -> this training table cannot be used in general case and taken to encode other files
1149 if(zeroentries > 50)
1151 HLTWarning("Warning! Only %i different 10 bit words out of %i are used, i.e. created Huffman Code table might not be optimal to encode other data", TIMEBINS-zeroentries, TIMEBINS);
1154 // FIXME use auto_ptr, use size of HuffmanArraySorted instead of TIMEBINS
1155 // initialise leaves of the tree as list (= queue) ofAliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct,
1156 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct * HuffmanTreeList = new AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct[filled];
1158 // initialise first element
1159 HuffmanTreeList[0].fleafcontents = HuffmanArraySorted[0];
1160 HuffmanTreeList[0].fleft = NULL;
1161 HuffmanTreeList[0].fright = NULL;
1162 HuffmanTreeList[0].fnext = &HuffmanTreeList[1];
1163 HuffmanTreeList[0].fprevious = NULL;
1166 // write list to screen
1167 // cout <<"Amplitude " << HuffmanTreeList[0].fleafcontents.famplitude << " | " << "Abundance "<< HuffmanTreeList[0].fleafcontents.fabundance << " | " << "Left " << HuffmanTreeList[0].fleft << " | " << "Right " << HuffmanTreeList[0].fright << " | " << "Next " << HuffmanTreeList[0].fnext << endl;
1169 // initialise 1 to filled-2 elements
1171 while(kk < filled-1)
1173 HuffmanTreeList[kk].fleafcontents = HuffmanArraySorted[kk];
1174 HuffmanTreeList[kk].fleft = NULL;
1175 HuffmanTreeList[kk].fright = NULL;
1176 HuffmanTreeList[kk].fnext = &HuffmanTreeList[kk+1];
1177 HuffmanTreeList[kk].fprevious = &HuffmanTreeList[kk-1];
1180 // write list to screen
1181 // cout <<"Amplitude " << HuffmanTreeList[kk].fleafcontents.famplitude << " | " << "Abundance "<< HuffmanTreeList[kk].fleafcontents.fabundance << " | " << "Left " << HuffmanTreeList[kk].fleft << " | " << "Right " << HuffmanTreeList[kk].fright << " | " << "Next " << HuffmanTreeList[kk].fnext << endl;
1186 // initialise last list entry with next pointer to NULL
1187 HuffmanTreeList[filled-1].fleafcontents = HuffmanArraySorted[filled-1];
1188 HuffmanTreeList[filled-1].fleft = NULL;
1189 HuffmanTreeList[filled-1].fright = NULL;
1190 HuffmanTreeList[filled-1].fnext = NULL;
1191 HuffmanTreeList[filled-1].fprevious = &HuffmanTreeList[filled-2];
1193 // initialise pointer to last list element:
1194 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* lastelement = &HuffmanTreeList[filled-1];
1197 // write last element to screen
1198 // cout <<"Amplitude " << HuffmanTreeList[filled-1].fleafcontents.famplitude << " | " << "Abundance "<< HuffmanTreeList[filled-1].fleafcontents.fabundance << " | " << "Left " << HuffmanTreeList[filled-1].fleft << " | " << "Right " << HuffmanTreeList[filled-1].fright << " | " << "Next " << HuffmanTreeList[filled-1].fnext << endl;
1200 //use this sorted list to build up the binary tree with root pointer to the beginning:
1201 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* root = CreateHuffmanTree(HuffmanTreeList, lastelement, filled);
1203 // abort if root = NULL (error already produced in CreateHuffmanTree function)
1204 delete [] HuffmanTreeList;
1212 // cout << "binary tree is now created " << endl;
1214 // create an array for the HuffmanCode data:
1215 fTranslationTable = new AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct[TIMEBINS];
1217 // initialise the array with validcodelengths 0 and codes = 0
1218 for(Int_t kk1 = 0; kk1 < TIMEBINS; kk1++)
1220 // validation test for correct HuffmanCode()
1221 // fTranslationTable[kk1].famplitude = TIMEBINS+1; // check if eventnames are written
1223 fTranslationTable[kk1].famplitude = kk1;
1224 fTranslationTable[kk1].fhuffmancode = 0;
1225 fTranslationTable[kk1].fvalidcodelength = 0;
1226 // fTranslationTable[kk1].morecode = NULL;
1229 // create HuffmanCode and abort when HuffmanCode produces errors
1230 if(HuffmanCode(root,fTranslationTable) == 1)
1236 // cout << "Huffman coding is now done " << endl;
1239 // print the Huffman code table to screen
1240 // for(Int_t kk = 0; kk < TIMEBINS; kk++)
1242 // if (fTranslationTable[kk].fvalidcodelength != 0)
1243 // cout << fTranslationTable[kk].famplitude << " | " << fTranslationTable[kk].fhuffmancode << " | " << fTranslationTable[kk].fvalidcodelength << endl;
1246 // findout maximal and minimal codelength and print them out
1247 UInt_t maxcodelength = fTranslationTable[0].fvalidcodelength;
1248 UInt_t mincodelength = TIMEBINS;
1250 for (Int_t kk2 = 0; kk2 < TIMEBINS; kk2++)
1252 // if(fTranslationTable[kk2].fvalidcodelength != 0) {cout << kk2 << " | " << fTranslationTable[kk2].fhuffmancode << " | " << fTranslation "Table[kk2].fvalidcodelength << endl;}
1254 if(fTranslationTable[kk2].fvalidcodelength > maxcodelength)
1255 { maxcodelength = fTranslationTable[kk2].fvalidcodelength;};
1256 if( (fTranslationTable[kk2].fvalidcodelength != 0) && (fTranslationTable[kk2].fvalidcodelength < mincodelength) )
1257 { mincodelength = fTranslationTable[kk2].fvalidcodelength;};
1260 // print results to screen
1261 HLTInfo("maximal codelength (DEC) = %i ", maxcodelength);
1262 HLTInfo("minimal codelength (DEC) = %i ", mincodelength);
1267 /** TTMergesort used by EntropyDecoding to sort translation table according to validcodelength from low to high */
1268 AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct* AliHLTCOMPHuffmanAltro::TTMergesort(AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct *unsortedarray, Int_t n)
1270 // see heaeder file for class documentation
1271 //divide array into two halfs: left and right (fleft.size = divlength)
1272 Int_t divlength = n >> 1;
1276 // error when unsorted array = NULL
1277 if (unsortedarray == NULL)
1279 HLTError("Error! Pointer to final merge sorted code table = NULL");
1282 return unsortedarray;
1286 // sort both halfs recursively:
1287 TTMergesort(unsortedarray, divlength); //left half
1288 TTMergesort(&unsortedarray[divlength], n-divlength); //right half
1291 // create temporary result array:
1292 AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct* temp = new AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct[n];
1297 // if left and right halves both have elements: chose the smaller one:
1298 for (ii = 0, jj = divlength, kk = 0; ii < divlength && jj < n;)
1300 if (unsortedarray[ii].fvalidcodelength < unsortedarray[jj].fvalidcodelength)
1302 temp[kk] = unsortedarray[ii];
1307 temp[kk] = unsortedarray[jj];
1315 // if one half is empty take elements of the other one:
1316 while (ii < divlength)
1318 temp[kk] = unsortedarray[ii];
1325 temp[kk] = unsortedarray[jj];
1330 // copy sorted temp array back into original data array
1331 for (Int_t ll = 0; ll < n; ll++)
1333 unsortedarray[ll] = temp[ll];
1339 // return pointer to original data array (which is sorted now)
1340 return unsortedarray;
1344 /** function for the entropy decoding, needed input: code table, input data pointer and size and pointer where to write decoded data */
1345 Int_t AliHLTCOMPHuffmanAltro::EntropyDecompression()
1347 // see heaeder file for class documentation
1349 // print translation table to screen
1350 // for(int kk= 0; kk < TIMEBINS; kk++)
1352 // cout << fTranslationTable[kk].famplitude << " | " << fTranslationTable[kk].fhuffmancode << " | " << fTranslationTable[kk].fvalidcodelength << endl;
1355 // sort translation table according to validcodelengths from low to high (codes that occur often are found quickly)
1356 fTranslationTable = TTMergesort(fTranslationTable, TIMEBINS);
1359 // print merge sorted translation table to screen
1360 // for(int kk= 0; kk < TIMEBINS; kk++)
1362 // cout << fTranslationTable[kk].famplitude << " | " << fTranslationTable[kk].fhuffmancode << " | " << fTranslationTable[kk].fvalidcodelength << endl;
1365 // do set output data first in order to know the size of the decompressed array!
1366 // take care of trailers and headers when decoding!
1368 // initialise reading pointer on compressed data
1369 AliHLTUInt64_t* pointerprop = (AliHLTUInt64_t*)fPointer2InData;
1371 // initialise writing pointer for decompressed output array
1372 AliHLTUInt64_t* pointeroutputprop = (AliHLTUInt64_t*) fPointer2OutData;
1374 // outputdata size initialised
1375 fOutputDataSize = 0;
1378 // cout << "input data size of encoded data (DEC) = " << fInputDataSize << endl;
1379 // cout << "output data size of decoded data (DEC) = " << fOutputDataSize << endl;
1381 // create temporary word to read out 1 bit from, maximal length: 64 bits */
1382 AliHLTUInt64_t codedata = 0;
1383 UInt_t codedatalength = 0;
1385 // number of 32-bit trailer and common data header words:
1386 UInt_t headerwords = 8;
1387 UInt_t header64 = headerwords >> 1;
1389 // initialise counter variables for input array:
1390 UInt_t idxwd = header64; // due to 8*32 = 4*64 bit header words
1393 // initialise counter variables for output array:
1394 UInt_t idxoutwd = header64; // due to 8*32 = 4*64 bit header words
1395 // UInt_t idx10out = 0; // only used for validation test
1396 UInt_t bitpsoutwd = 0;
1398 // write header to output (two words input header in one word output header):
1399 UInt_t head64cntr = 0;
1401 while(head64cntr < header64)
1403 pointeroutputprop[head64cntr] = pointerprop[head64cntr];
1406 //cout << "header line in output stream (HEX) = " << hex << pointeroutputprop[head64cntr] << dec << endl;
1411 // end of encoded ALTRO-blocks [Byte] = finputdatasize - (number of 32-bit-trailer-words + 1) / 4
1412 // match this with idxwd as number of 64-bit-words (endNdx[#64-bit-wds] = endNdx[#8-bit-wds]*8/64)
1413 UInt_t lastfullline = (fInputDataSize) >> 3;
1414 UInt_t lastbit = (fInputDataSize << 3) & 0x3F;
1415 UInt_t lastcodeline = lastfullline - ((fNrcuTrailerwords +1) >> 1);
1425 // initialise last valid bit position and trailer array
1426 AliHLTUInt32_t lastvalidbitpos = 0;
1427 AliHLTUInt64_t* trailer = new AliHLTUInt64_t[fNrcuTrailerwords];
1428 if (!trailer) return -1;
1431 // cout << "last bit (DEC) = " << lastbit << endl;
1432 // cout << "lastfullline (DEC) = " << lastfullline << endl;
1433 // cout << "lastcodeline(DEC) = " << lastcodeline << endl;
1434 // cout << "second last code line data (HEX) = " << hex << pointerprop[lastcodeline-1] << dec << endl;
1435 // cout << "last code line data (HEX) = " << hex << pointerprop[lastcodeline] << dec << endl;
1436 // cout << "last full line data (HEX) = " << hex << pointerprop[lastfullline] << dec << endl;
1438 // get last valid bit position (first 32 bit word in first trailer line after code
1440 if (fNrcuTrailerwords < 3) // then lastfullline = only trailerline
1442 lastvalidbitpos = (pointerprop[lastfullline] >> 32);
1444 // first trailerword
1445 trailer[0] = ((pointerprop[lastfullline] << 32 ) >> 32);
1447 // second trailerword
1448 if(fNrcuTrailerwords == 2)
1450 trailer[1] = ((pointerprop[lastfullline+1] << 32) >> 32);
1455 lastvalidbitpos = (pointerprop[lastfullline-1] >> 32);
1457 // first trailerword
1458 trailer[0] = ((pointerprop[lastfullline-1] << 32 ) >> 32);
1460 //second trailerword
1461 trailer[1] = (pointerprop[lastfullline] >> 32);
1463 // third trailerword
1464 trailer[2] =((pointerprop[lastfullline] << 32 ) >> 32);
1468 // cout << "last valid bit position (DEC) = " << lastvalidbitpos << endl;
1470 // warning if one of the trailer words is zero:
1471 for (UInt_t kk = 0; kk < fNrcuTrailerwords; kk++)
1473 if(trailer[kk] == 0)
1475 HLTWarning("Warning! Trailer word %i is zero",kk+1);
1480 // print trailer array to screen
1481 // for(Int_t ii=0; ii < fNrcuTrailerwords; ii++)
1483 // cout << "trailerword " << ii+1 << " after getting whole trailer (HEX) = " << hex << trailer[ii] << dec << endl;
1486 // find minmal validcodelength from first entry of translation table and
1487 // read in minimal validcodelength bits if codedata is zero...
1488 UInt_t minimalcodelength = fTranslationTable[0].fvalidcodelength;
1491 // cout << "minimal codelength (DEC) = " << minimalcodelength << endl;
1493 Int_t readnewcode = 1; // read new code = 1; go on with old code = 0
1496 // NEW (bitpswd >= lastvalidbitpos) instead of (bitpswd > lastvalidbitpos)
1497 while (!((idxwd >= lastcodeline) && (bitpswd >= lastvalidbitpos)) )
1499 if((idxwd == lastcodeline+1) && (bitpswd == 0)) break; // abortion when lastvalidbitpos = 64
1501 if (codedatalength < 64) // if codedata can still get one further bit
1503 // if new code word is read before end position
1504 if((readnewcode == 1) && !((idxwd >= lastcodeline) && (bitpswd + minimalcodelength > lastvalidbitpos)))
1506 // codedata gets next bits from encoded input file:
1507 codedata <<= minimalcodelength; //shift bits left
1509 if (bitpswd + minimalcodelength < 65) // all bits in the same line
1511 codedata |= ((pointerprop[idxwd] << bitpswd)) >> (64 - minimalcodelength); //append bits from input file to the right
1513 else // some of this bits in the next line
1515 // append bits of current line to the right end of codedata
1516 codedata |= (((pointerprop[idxwd] << bitpswd)) >> (bitpswd)) << (minimalcodelength - 64 + bitpswd);
1518 // append bits of next line to the right end of codedata
1519 codedata |= (pointerprop[idxwd+1] >> (128 - minimalcodelength - bitpswd)); // 128 - mcl - bitpswd = 64 - (mcl - (64 - bitpswd))
1522 codedatalength += minimalcodelength;
1524 // new code is read, set readnewcode back to 0 again
1527 // go and get next input bit
1528 bitpswd += minimalcodelength;
1532 // codedata gets on bit after another from encoded input file:
1533 codedata <<= 1; //shift one bit left
1534 codedata |= ((pointerprop[idxwd] << bitpswd)) >> 63; //append next bit from input file to the right
1538 // go and get next input bit
1542 // go and get next input bit
1546 bitpswd = bitpswd & 0x3F;
1549 // compare if new codedata is in translation table:
1550 for(UInt_t kk = 0; kk < TIMEBINS; kk++)
1552 // stopping when current codedatalength smaller than lookup validcodelength (i.e. current code not in table, read next bit)
1553 if(fTranslationTable[kk].fvalidcodelength > codedatalength)
1558 if(fTranslationTable[kk].fhuffmancode == codedata) //lookup bit pattern
1560 if(fTranslationTable[kk].fvalidcodelength == codedatalength) //lookup correct codelength
1563 // if( idxoutwd >= 2636)
1565 // cout << "write 10 bit word to decoded output (DEC) = " << fTranslationTable[kk].famplitude << endl;
1566 // cout << "current idxwd (DEC) = " << idxwd << endl;
1567 // cout << "current idxoutwd (DEC) = " << idxoutwd << endl;
1569 if(bitpsoutwd + 10 < 65) //fits in old line
1571 // valdidation test for end of decoded data
1572 // print all relevant quantities to screen
1575 // cout << "current input in codedata (HEX) = " << hex << (pointerprop[idxwd] << bitpswd) << dec << endl;
1576 // cout << "current idxwd (DEC) = " << idxwd << endl;
1577 // cout << "current bitpswd (DEC) = " << bitpswd << endl;
1578 // cout << "current idxoutwd (DEC) = " << idxoutwd << endl;
1579 // cout << "current bitpsoutwd (DEC) = " << bitpsoutwd << endl;
1580 // cout << "decoding value (DEC) = " << codedata << endl;
1581 // cout << "value length (DEC) = " << codedatalength << endl;
1582 // cout << "10 bit value (HEX) = " << hex << fTranslationTable[kk].famplitude << dec << endl;
1585 pointeroutputprop[idxoutwd] |= ((AliHLTUInt64_t)(fTranslationTable[kk].famplitude)) << bitpsoutwd;
1588 // if (idxoutwd > 362880)
1590 // cout << "updated output line (HEX) = " <<hex << pointeroutputprop[idxoutwd] <<dec << endl;
1593 // goto next 10-bits output position
1596 if(bitpsoutwd == 64) {bitpsoutwd = 0; ++idxoutwd;};
1599 else //needs start of new line
1602 pointeroutputprop[idxoutwd] |= ((AliHLTUInt64_t)(fTranslationTable[kk].famplitude)) << (bitpsoutwd);
1604 ++idxoutwd; //start new line
1609 // cout << "current input in codedata (HEX) = " << hex << (pointerprop[idxwd] << bitpswd) << dec << endl;
1610 // cout << "current idxwd (DEC) = " << idxwd << endl;
1611 // cout << "current bitpswd (DEC) = " << bitpswd << endl;
1612 // cout << "current idxoutwd (DEC) = " << idxoutwd << endl;
1613 // cout << "current bitpsoutwd (DEC) = " << bitpsoutwd << endl;
1614 // cout << "decoding value (DEC) = " << codedata << endl;
1615 // cout << "value length (DEC) = " << codedatalength << endl;
1616 // cout << "10 bit value (HEX) = " << hex << fTranslationTable[kk].famplitude << dec << endl;
1620 AliHLTUInt64_t buffer = fTranslationTable[kk].famplitude;
1621 buffer >>= (64 - bitpsoutwd);
1623 pointeroutputprop[idxoutwd] = buffer;
1626 // if (idxoutwd > 362880)
1628 // cout << "new line (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
1631 // go to next bit position
1635 // set buffers to zero again
1639 // prepare codedata to read new code word
1645 // go on with next code bits from input
1651 else // if *morecode is used
1654 HLTError("Error! Valid codelength for current decoding is larger than 64 bits, error in recognising the correct code");
1662 // last (incomplete) line from input encoded data
1663 // after all code is read, bitpsoutwd at lastvalidbitpos
1664 // -> go to next byte (i.e. start of trailer)
1667 // cout << "bit position after decoding (DEC) = " << bitpsoutwd << endl;
1668 // cout << "line position after decoding (DEC) = " << idxoutwd << endl;
1670 // warning if byte position is not 8-bits aligned
1671 if ((bitpsoutwd & 0x07) != 0 )
1673 HLTWarning("Warning! Bit position after decoding %i is not aligned to 8 bits", bitpsoutwd);
1676 if(bitpsoutwd + 32 < 65) // trailer fits in current line, append on the right
1678 pointeroutputprop[idxoutwd] <<= 32;
1680 pointeroutputprop[idxoutwd] |= trailer[0];
1686 pointeroutputprop[idxoutwd] <<= 64 - bitpsoutwd;
1687 pointeroutputprop[idxoutwd]|= (trailer[0] >> (bitpsoutwd - 32));
1692 // get rid of upper, already written bits
1693 trailer[0] <<= 96 - bitpsoutwd;
1694 trailer[0] >>= 96 - bitpsoutwd;
1696 pointeroutputprop[idxoutwd] = trailer[0]; // write lower bits to next line
1701 if(fNrcuTrailerwords > 1)
1704 if(bitpsoutwd == 64)
1710 for(UInt_t ii = 1; ii < fNrcuTrailerwords; ii++)
1712 // write second trailer to output data
1713 if(bitpsoutwd + 32 < 65) // trailer fits in current line, append on the right
1715 pointeroutputprop[idxoutwd] <<= 32;
1717 pointeroutputprop[idxoutwd] |= trailer[ii];
1721 if(bitpsoutwd == 64)
1729 pointeroutputprop[idxoutwd] <<= 64 - bitpsoutwd;
1730 pointeroutputprop[idxoutwd]|= (trailer[ii] >> (bitpsoutwd - 32));
1735 // get rid of upper, already written bits
1736 trailer[ii] <<= 96 - bitpsoutwd;
1737 trailer[ii] >>= 96 - bitpsoutwd;
1739 pointeroutputprop[idxoutwd] = trailer[ii]; // write lower bits to next line
1746 // cout << "bitpswd after decoding (DEC) = " << bitpswd << endl;
1747 // cout << "bitpsoutwd after decoding (DEC) = " << bitpsoutwd << endl;
1748 // cout << "idxwd after decoding (DEC) = " << idxwd << endl;
1749 // cout << "idxoutwd after decoding (DEC) = " << idxoutwd << endl;
1751 // write trailer to decoded output
1753 // set fOutputDataSize in byte:
1754 // idxoutwd*8 = number of whole 64 bits words in byte
1755 // bitpsoutwd/8 = number of wohle 8 bits words within last idxoutwd
1756 // (bitpsoutwd%8)?1:0 = determine whether one more byte has to be used for "left over" bits
1757 fOutputDataSize = (Int_t) ((idxoutwd << 3) + (bitpsoutwd >> 3) + ((bitpsoutwd & 0x7) ? 1 : 0) );
1760 // error and abort when output data size smaller than input data size (impossible when decompressing)
1761 if(fOutputDataSize < fInputDataSize)
1763 HLTError("Error! Data size for decompressed output stream (bytes) %i is smaller than compressed input data size (bytes) %i", fOutputDataSize, fInputDataSize);
1769 // cout << "output data size (DEC) = " << fOutputDataSize << endl;
1774 Int_t AliHLTCOMPHuffmanAltro::CalcEntropy(const AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct* occurrencetable)
1776 // calculate entropy of 10 bit values
1777 if (!occurrencetable) occurrencetable=fTrainingTable;
1778 if (!occurrencetable) return -ENODATA;
1780 int totalnumber=accumulate(occurrencetable, occurrencetable+TIMEBINS, int(0), AliHLTCOMPHuffmanOccurrenceSum());
1781 if (totalnumber<1) {
1782 HLTWarning("can not calculate entropy from empty table");
1788 const double l2 = log(2.0);
1789 for(UInt_t jj = 0; jj < TIMEBINS; jj++) {
1790 double value=occurrencetable[jj].fabundance;
1791 if (value<1.0) continue;
1792 entropy += (- (Double_t) value / (Double_t) totalnumber ) * log( ( (Double_t) value / (Double_t) totalnumber )) / (l2);
1799 /* CopyData is just a function for performance testing */
1800 Int_t AliHLTCOMPHuffmanAltro::CopyData()
1802 // see heaeder file for class documentation
1803 // output data: fPointer2OutData (to 8-bit words)
1804 // initialise propagation pointer for output array
1805 AliHLTUInt32_t* pointer2InData = (AliHLTUInt32_t*) fPointer2InData;
1806 AliHLTUInt32_t* pointeroutprop = (AliHLTUInt32_t*) fPointer2OutData;
1808 //first output word has to be initialised
1809 pointeroutprop[0] = 0;
1811 fOutputDataSize = fInputDataSize;
1813 // initialise required variables for input reading:
1814 AliHLTUInt32_t data10 = 0; // temporary number to read out 10bit word with
1819 // number of 32-bit trailer and common data header words:
1820 // (taken out of compression!)
1821 // UInt_t headerwords = 8;
1823 // initialise required variables for ouput creation:
1824 UInt_t idxoutwd = 0;
1825 // Int_t bitcounter = 0; // additional test for number of read in 10 bit words
1826 // Int_t sumlength = 0; // additional test for length of encoded file
1828 UInt_t endNdx = (fInputDataSize>>2)-fNrcuTrailerwords;
1830 // start reading and encoding input data (which are 10 bit words):
1831 while (idxwd < endNdx)
1833 // write input data in temp and cut out 10 bits with mask 0x3FF
1834 data10 = (pointer2InData[idxwd] >> bitpswd ) & 0x3FFU;
1837 //cout << "current 10 bits word (DEC) = " << data10 << endl;
1839 // if number of bits left in read input less than ten, get remaining bits from next 32bit word
1842 data10 |= (pointer2InData[idxwd + 1]) << (32 - bitpswd);
1847 // print first 10 bits words to screen
1850 // cout << "read data: " << hex << data10 << dec << endl;
1853 // write data to 32 bit output:
1854 pointeroutprop[idxoutwd] |= (data10 << bitpswd);
1858 pointeroutprop[idxoutwd + 1] = (data10 >> (32 - bitpswd));
1862 // cout << "next bitpswd (DEC) = " << bitpswd << endl;
1864 ++idx10; // go on reading 10 bit word
1866 // index word reads position of 32bit word in input array
1867 idxoutwd = (idx10 * 10);
1868 bitpswd = idxoutwd & 0x1F;
1871 // bit position word reads position in 32bit word when 10 bits are read out
1875 // cout << "output data size (DEC) = " << fOutputDataSize << endl;
1876 // cout << "sum of codelengths (DEC) = " << sumlength << endl;
1877 // cout << "number of 10 bits words (DEC) = " << bitcounter << endl;
1882 void AliHLTCOMPHuffmanAltro::Print(Option_t* option) const
1886 if (strcmp(option, "trainingtable")==0) {
1887 // print fTrainingTable to screen (non-zero entries only):
1888 if (!fTrainingTable) {
1889 cout << "no training table" << endl;
1892 for(Int_t jj = 0; jj < TIMEBINS; jj++) {
1893 if(fTrainingTable[jj].fabundance != 0)
1894 cout << jj << " | " << fTrainingTable[jj].famplitude << " | " << fTrainingTable[jj].fabundance << endl;
1899 if (strcmp(option, "translationtable")==0) {
1900 // print fTranslationTable to screen (non-zero entries only):
1901 if (!fTranslationTable) {
1902 cout << "no translation table" << endl;
1905 for(Int_t jj = 0; jj < TIMEBINS; jj++) {
1906 if(fTranslationTable[jj].fvalidcodelength != 0)
1907 cout << jj << " | " << fTranslationTable[jj].fhuffmancode << " | " << fTranslationTable[jj].fvalidcodelength << endl;
1912 if (strcmp(option, "entropy")==0) {
1913 cout << "Calculated entropy = " << fEntropy << endl;