]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/comp/AliHLTCOMPHuffmanAltro.cxx
excluding deprecated classes from libAliHLTComp, library stays as an empty body for...
[u/mrichter/AliRoot.git] / HLT / comp / AliHLTCOMPHuffmanAltro.cxx
CommitLineData
e3107b54 1//-*- Mode: C++ -*-
2// $Id$
3
4///**************************************************************************
5///* This file is property of and copyright by the ALICE HLT Project *
6///* All rights reserved. *
7///* *
8///* Primary Author: Jenny Wagner (jwagner@cern.ch) *
9///* *
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///**************************************************************************
18
19/// @file AliHLTCOMPHuffmanAltro.cxx
20/// @author Jenny Wagner
21/// @date 29-08-2007
22/// @brief The Huffman compressor
23///
c2440081 24
25#include "AliHLTCOMPHuffmanAltro.h"
e3107b54 26#include "AliRawReaderMemory.h"
27#include "AliAltroRawStreamV3.h"
28#include <memory>
c2440081 29
30#if __GNUC__ >= 3
31using namespace std;
32#endif
33
e3107b54 34#include <numeric>
35using std::accumulate;
36
37namespace
38{
39 // Helper class for std::accumulate algorithm.
40 class AliHLTCOMPHuffmanOccurrenceSum {
41 public:
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;
47 }
48 };
49} // end of namespace
50
51/** ROOT macro for the implementation of ROOT specific class methods */
c2440081 52ClassImp(AliHLTCOMPHuffmanAltro)
53
c2440081 54AliHLTCOMPHuffmanAltro::AliHLTCOMPHuffmanAltro()
8bdb460b 55 : TObject(), AliHLTLogging()
e3107b54 56 , fpRawReader(NULL)
57 , fpAltroRawStream(NULL)
58 , fTrainingMode(0)
59 , fCompressionSwitch(0)
60 , fPointer2InData(NULL)
61 , fPointer2OutData(NULL)
62 , fInputDataSize(0)
63 , fOutputDataSize(0)
64 , fNrcuTrailerwords(0)
65 , fEntropy(0.0)
66 , fVerbosity(0)
67 , fTrainingTable(NULL)
68 , fTranslationTable(NULL)
c2440081 69{
e3107b54 70 // standard constructor
c2440081 71}
72
bf7a3243 73AliHLTCOMPHuffmanAltro::AliHLTCOMPHuffmanAltro(Bool_t compressionswitch, Bool_t trainingmode, AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct* translationtable, Int_t nrcutrailerwords)
8bdb460b 74 : TObject(), AliHLTLogging()
e3107b54 75 , fpRawReader(NULL)
76 , fpAltroRawStream(NULL)
77 , fTrainingMode(trainingmode)
78 , fCompressionSwitch(compressionswitch)
79 , fPointer2InData(NULL)
80 , fPointer2OutData(NULL)
81 , fInputDataSize(0)
82 , fOutputDataSize(0)
83 , fNrcuTrailerwords(nrcutrailerwords)
84 , fEntropy(0.0)
85 , fVerbosity(0)
86 , fTrainingTable(NULL)
87 , fTranslationTable(translationtable)
c2440081 88{
e3107b54 89 // constructor
c2440081 90}
91
c2440081 92AliHLTCOMPHuffmanAltro::~AliHLTCOMPHuffmanAltro()
93{
e3107b54 94 /// destructor
95 if (fpAltroRawStream) delete fpAltroRawStream;
96 fpAltroRawStream=NULL;
97 if (fpRawReader) delete fpRawReader;
98 fpRawReader=NULL;
99
100 if (fTrainingTable) delete [] fTrainingTable;
101 fTrainingTable=NULL;
c2440081 102}
103
e3107b54 104int AliHLTCOMPHuffmanAltro::AddInputData(UChar_t* memory, ULong_t datasize, Int_t equipmentId)
c2440081 105{
e3107b54 106 /// SetInputData takes input data pointer and input data size from component class
107 if (memory == NULL) {
108 return -EINVAL;
109 };
c2440081 110
e3107b54 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");
114 return -ENODATA;
115 }
116
117 // FIXME: fPointer2InData is obsolete
118 fPointer2InData = (AliHLTUInt8_t*)memory;
119 fInputDataSize = datasize; // size in bytes
120
121 if (!fpRawReader) {
122 std::auto_ptr<AliRawReaderMemory> rawReader(new AliRawReaderMemory);
123 std::auto_ptr<AliAltroRawStreamV3> rawStream(new AliAltroRawStreamV3(rawReader.get()));
124
125 if (!rawReader.get() || !rawStream.get()) {
126 return -ENOMEM;
c2440081 127 }
e3107b54 128
129 fpRawReader=rawReader.release();
130 fpAltroRawStream=rawStream.release();
131 }
132
133 fpRawReader->AddBuffer(memory, datasize, equipmentId);
134
135 return 0;
c2440081 136}
137
e3107b54 138int AliHLTCOMPHuffmanAltro::Reset()
139{
140 /// Reset and prepare for new event
141 if (fpRawReader) {
142 fpRawReader->ClearBuffers();
143 }
144 if (fpAltroRawStream) {
145 fpAltroRawStream->Reset();
146 }
147
148 InitNewTrainingTable();
149
150 return 0;
151}
c2440081 152
e3107b54 153int AliHLTCOMPHuffmanAltro::SetOutputData(AliHLTUInt8_t* outputdata, unsigned long outputsize)
c2440081 154{
e3107b54 155 /// SetOuptputData takes output data pointer and outputsize from component class
156 if (outputdata == NULL) {
157 return -EINVAL;
158 };
159
c2440081 160 fPointer2OutData = (AliHLTUInt64_t*) outputdata;
161 fOutputDataSize = outputsize;
162
c2440081 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)
e3107b54 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");
169 return -ENOSPC;
c2440081 170 }
e3107b54 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");
174 return -ENOSPC;
c2440081 175 }
e3107b54 176 }
177
178 return 0;
c2440081 179}
180
c2440081 181unsigned long AliHLTCOMPHuffmanAltro::GetOutputDataSize()
182{
e3107b54 183 // GetOutputDataSize delivers output data size for component class to arrange blocks for output writing
c2440081 184 // error when fOuputDataSize = 0; (not by training as there is no output when training)
e3107b54 185 if((fOutputDataSize == 0) && (fTrainingMode == kFALSE)) {
186 HLTError("Error! Calculated output data size is zero");
187 };
c2440081 188
189 return fOutputDataSize;
190}
191
e3107b54 192int AliHLTCOMPHuffmanAltro::InitNewTrainingTable()
c2440081 193{
e3107b54 194 // Initialise training table
195 if (!fTrainingTable) fTrainingTable = new AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct[TIMEBINS];
196 if (!fTrainingTable) return -ENOMEM;
c2440081 197
198 //initialise this array:
e3107b54 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!!!
203 }
204
205 return 0;
c2440081 206}
207
e3107b54 208int AliHLTCOMPHuffmanAltro::SetHuffmanData(AliHLTCOMPHuffmanData* huffmandata) const
c2440081 209{
e3107b54 210 // write produced code and occurrence table to Huffman Data
211 return huffmandata->InitHuffmanData(fTrainingTable, fTranslationTable);
c2440081 212}
213
e3107b54 214int AliHLTCOMPHuffmanAltro::GetTrainingTable(const AliHLTCOMPHuffmanData* huffmandata)
c2440081 215{
c2440081 216 // take translation table from HuffmanData
e3107b54 217 huffmandata->GetOccurrenceTable(fTrainingTable);
218 if (fVerbosity>0) Print("trainingtable");
c2440081 219
e3107b54 220 return 0;
c2440081 221}
222
e3107b54 223int AliHLTCOMPHuffmanAltro::GetTranslationTable(const AliHLTCOMPHuffmanData* huffmandata)
c2440081 224{
e3107b54 225 // initialise fTranslationTable
226 if (fTranslationTable) delete fTranslationTable;
bf7a3243 227 fTranslationTable = new AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct[TIMEBINS];
e3107b54 228 if (!fTranslationTable) return -ENOMEM;
c2440081 229
e3107b54 230 for(Int_t kk = 0; kk < TIMEBINS; kk++) {
231 fTranslationTable[kk].famplitude = 0;
232 fTranslationTable[kk].fhuffmancode = 0;
233 fTranslationTable[kk].fvalidcodelength = 0;
234 }
c2440081 235
236 // take translation table from HuffmanData
e3107b54 237 huffmandata->GetCodeTable(fTranslationTable);
238 if (fVerbosity>0) Print("translationtable");
c2440081 239
e3107b54 240 return 0;
c2440081 241}
242
243/** ProcessData function to process data compression or decompression */
244void AliHLTCOMPHuffmanAltro::ProcessData()
245{
246 // see header file for class documentation
247 // set mode to process:
248 if(fCompressionSwitch == kTRUE && fTrainingMode == kFALSE) // encoding without training
249 {
250 EntropyCompression();
251
252 // information about compression ratio
c2440081 253 HLTDebug("original filesize (bytes) = %d", fInputDataSize);
254 HLTDebug("compressed filesize (bytes) = %d", fOutputDataSize);
bf7a3243 255 HLTDebug("compression ratio after Huffman encoding is %f", ((Double_t) fOutputDataSize)/fInputDataSize);
c2440081 256 }
257 else
258 {
259 if(fCompressionSwitch == kTRUE && fTrainingMode == kTRUE) // encoding with training
260 {
261 TrainingData();
262
263 // information about calculated entropy (contained in GetEntropy()) and compression ratio
264 CalcEntropy();
265 GetEntropy();
266 }
267 else // decoding (no training possible, which is checked for errors by component)
268 {
269 EntropyDecompression();
270
271 // information about compression ratio
c2440081 272 HLTDebug("compressed filesize (bytes) = %d", fInputDataSize);
273 HLTDebug("filesize after decoding (bytes) = %d", fOutputDataSize);
bf7a3243 274 HLTDebug("compression ratio calculated from Huffman decompressing has been %f",((Double_t) fInputDataSize)/fOutputDataSize);
c2440081 275 }
276 }
277}
278
c2440081 279Double_t AliHLTCOMPHuffmanAltro::GetEntropy()
280{
c2440081 281 // Information about calculated entropy
8bdb460b 282 if (fVerbosity>0) HLTInfo("Calculated entropy = %f",fEntropy);
c2440081 283
284 return fEntropy;
285}
286
287/** Compression: take raw input data, code table and put out entropy encoded data */
288Int_t AliHLTCOMPHuffmanAltro::EntropyCompression()
289{
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;
294
295 //first output word has to be initialised
296 pointeroutputprop[0] = 0;
297
298 // initialise output size
299 fOutputDataSize = 0;
300
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
306
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;
311
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
315
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
319
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)
323 {
324 HLTError("Error! Input data size (bytes) %i cannot be divided into 32 bit words", fInputDataSize);
325
326 return 1;
327 };
328
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)
331 {
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));
333
334 return 1;
335 };
336
337 // last line of 32-bits which is to be encoded
338 UInt_t endNdx = (fInputDataSize>>2)-fNrcuTrailerwords;
339
340 // write header to output (two 32-bits words input header in one 64-bits word output header):
341 UInt_t headcntr = 0;
342 UInt_t headwordcntr = 0;
343
344 while(headcntr != (headerwords >> 1))
345 {
346 // write first header word to the left
347 pointeroutputprop[headcntr] = ((AliHLTUInt64_t) pointer2InData[headwordcntr]);
348
349 // write second header word to the right
350 pointeroutputprop[headcntr] |= ( ((AliHLTUInt64_t) pointer2InData[headwordcntr+1]) << 32);
351
352 // goto next header line and next two header words
353 ++headcntr;
354 headwordcntr += 2;
355 }
356
357 // EntropyCompression() for 10-bit values of ALTRO-Blocks:
358 while (idxwd < endNdx)
359 {
360 // write input data in data10 and cut out 10 bits with mask 0x3FFU = 0011 1111 1111
361 data10 = (pointer2InData[idxwd] >> bitpswd ) & 0x3FFU;
362
363 // validation test
364 // cout << "10 bit data cut out from data10 = " << data10 << endl;
365
366 // if number of bits left in read input less than 10, get remaining bits from next 32-bits word
367 if(bitpswd > 21)
368 {
369 // validation test
370 // cout << "adding bits from next word at bit position " << bitpswd << endl;
371
372 data10 |= (pointer2InData[idxwd + 1]) << (32 - bitpswd);
373 data10 &= 0x3FFU;
374
375 // validation test
376 // cout << "complete 10-bits word = << data10 << endl;
377 };
378
379 // validation test
380 // print first 100 10-bits words with resp.code and validcodelength to screen...
381 // if (idx10 < 101)
382 // {
bf7a3243 383 // cout << "read 10-bits word (HEX) = " << hex << data10 << dec <<" with code (DEC) = " << fTranslationTable[data10].fhuffmancode << " and validcodelength (DEC) = " << fTranslationTable[data10].fvalidcodelength << endl;
c2440081 384 // };
385
386 // start encoding of codes with less than 65 bits codelength
bf7a3243 387 if(fTranslationTable[data10].fvalidcodelength < 65)
c2440081 388 {
389 // error and abortion when validcodelength = 0
bf7a3243 390 if (fTranslationTable[data10].fvalidcodelength == 0)
c2440081 391 {
392 HLTError("Error! Valid codelength of read 10 bit word (DEC) %i is zero", data10);
393
394 return 1;
395 }
396
397 // validation test
398 // bitcounter += 1;
bf7a3243 399 // sumlength += fTranslationTable[data10].fvalidcodelength;
c2440081 400
bf7a3243 401 if(fTranslationTable[data10].fvalidcodelength + bitpsoutwd < 64) //if new code fits in current output line
c2440081 402 {
403 // validation test
bf7a3243 404 // cout << "writing code (HEX) = " << hex << fTranslationTable[data10].fhuffmancode << dec << " to line (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
c2440081 405
406 // shift line to right
bf7a3243 407 pointeroutputprop[idxoutwd] <<= fTranslationTable[data10].fvalidcodelength;
c2440081 408
409 // append code at left side of line
bf7a3243 410 pointeroutputprop[idxoutwd] |= fTranslationTable[data10].fhuffmancode;
c2440081 411
412 // validation test
413 // cout << "code written and current line updated to (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
414 }
415 else //if not, write lowest bits to next line
416 {
417 // validation test
bf7a3243 418 // cout << "writing bits of code (HEX) = " << hex << fTranslationTable[data10].fhuffmancode << dec << " to line (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
c2440081 419
420 // create temporary variable for performance gain:
bf7a3243 421 Int_t restcode = fTranslationTable[data10].fvalidcodelength - 64 + bitpsoutwd;
c2440081 422
423 // shift line completely to the right
424 pointeroutputprop[idxoutwd] <<= (64 - bitpsoutwd);
425
426 // append upper bits of code to this line
bf7a3243 427 pointeroutputprop[idxoutwd] |= (fTranslationTable[data10].fhuffmancode >> (restcode));
c2440081 428
429 // validation test
430 // cout << "code bits written and current line updated to (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
431
432 // write lowest code bits to next line
433
434 ++idxoutwd;
435
436 // trick to cut out already written bits from code
bf7a3243 437 AliHLTUInt64_t tempbuffer = fTranslationTable[data10].fhuffmancode;
c2440081 438 tempbuffer <<= 64-bitpsoutwd; // shift away written code
439 tempbuffer >>= 64-bitpsoutwd; // shift back to get lowest bits
440
441 pointeroutputprop[idxoutwd] = tempbuffer;
442
443 // validation test
444 // cout << "code bits written and next line started as (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
445 }
446 }
447 else // if code is longer than 64 bits: use *morecode (not tested therefore left away)
448 {
449 HLTError("Error! Huffman Code Table does not contain codes with valid codelength longer than 64 bits");
450
451 return 1;
452
453 }
454
455 // validation test
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;
459
460 // calculate new positions
bf7a3243 461 bitpsoutwd = (fTranslationTable[data10].fvalidcodelength + bitpsoutwd) & 0x3F;
c2440081 462
463 ++idx10; // go on reading 10 bit word
464
465 // bit position word reads position in 32bit word when 10 bits are read out
466 bitpswd = (idx10 * 10) & 0x1F;
467
468 // index word reads position of 32bit word in input array
469 idxwd = ((idx10 * 10)>>5)+8;
470
471 // validation test
472 //if(idxoutwd > 2635)
473 // {
474 // cout << " encoding value (HEX) = " << hex << data10 << dec << endl;
bf7a3243 475 // cout << " code (HEX) = " << hex << fTranslationTable[data10].fhuffmancode << dec << endl;
476 // cout << " valid code length (DEC) = " << fTranslationTable[data10].fvalidcodelength << endl;
c2440081 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;
480 // }
481
482 }// end of encoding (while loop)
483
484 // if new line is already started
485 if(bitpsoutwd == 0)
486 {
487 --idxoutwd;
488 bitpsoutwd = 64;
489 }
490 else
491 {
492 // fill rest of line with zeroes
493 pointeroutputprop[idxoutwd] <<= (64 - bitpsoutwd);
494 }
495
496 // next 32 bits are to memorise first bitposition after the code
497 UInt_t lastvalidbitps = bitpsoutwd;
498
499 // validation test
500 // cout << "last bitpsoutwd = lastvalidbitps (DEC) = " << bitpsoutwd << endl;
501
502 // validation test
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;
506
507 // start new line and write last valid bit position and trailer words there:
508 bitpsoutwd = 32;
509 ++idxoutwd;
510
511 pointeroutputprop[idxoutwd] = lastvalidbitps;
512
513 // validation test
514 // cout << "first trailer line with lastvalidbitps (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
515 // cout << "idxoutwd (DEC) = " << idxoutwd << endl;
516
517 // write first trailerword
518 bitpsoutwd = 64;
519 pointeroutputprop[idxoutwd] <<= 32;
520 pointeroutputprop[idxoutwd] |= pointer2InData[endNdx];
521
522 // validation test
523 // cout << "first trailer line with lastvalidbitpos and first trailerword (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
524
525 if(fNrcuTrailerwords > 1) // if there is more than one trailerword
526 {
527 ++idxoutwd;
528 bitpsoutwd = 32;
529
530 pointeroutputprop[idxoutwd] = pointer2InData[endNdx + 1]; // write second
531
532 // validation test
533 // cout << "last trailer line with second trailerword (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
534 // cout << "idxoutwd (DEC) = " << idxoutwd << endl;
535
536 if (fNrcuTrailerwords == 3) // write third
537 {
538 bitpsoutwd = 64;
539
540 pointeroutputprop[idxoutwd] <<= 32;
541 pointeroutputprop[idxoutwd] |= pointer2InData[endNdx +2];
542
543 // validation test
544 // cout << "last trailer line with last trailerword (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
545 }
546 }
547
548 // validation tests
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;
556
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));
561
562 // error and abortion when output data size for encoding is larger than input data size
563 if(fOutputDataSize > fInputDataSize)
564 {
565 HLTError("Error! Calculated data size for compressed output stream is larger than input data size");
566
567 return 1;
568 };
569
570 // validation test
571 // cout << "output data size (DEC) = " << fOutputDataSize << endl;
572
573 return 0;
574}
575
576/** Mergesort used by TrainingData to sort an array with n entries from high abundance to low abundance */
bf7a3243 577AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct* AliHLTCOMPHuffmanAltro::Mergesort(AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct *unsortedarray, Int_t n)
c2440081 578{
579 // see header file for class documentation
bf7a3243 580 //divide array into two halfs: left and right (fleft.size = divlength)
c2440081 581 Int_t divlength = n >> 1;
582
583 if (n==1)
584 {
585 // error when unsorted array = NULL
586 if (unsortedarray == NULL)
587 {
588 HLTError("Error! Pointer to final merge sorted abundance array = NULL");
589 };
590
591 return unsortedarray;
592 }
593 else
594 {
595 // sort both halfs recursively:
596 Mergesort(unsortedarray, divlength); //left half
597 Mergesort(&unsortedarray[divlength], n-divlength); //right half
598
599 // merge together:
600 // create temporary result array:
bf7a3243 601 AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct* temp = new AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct[n];
c2440081 602
603 // counters:
604 Int_t ii, jj, kk;
605
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;)
608 {
bf7a3243 609 if (unsortedarray[ii].fabundance > unsortedarray[jj].fabundance)
c2440081 610 {
611 temp[kk] = unsortedarray[ii];
612 ++ii;
613 }
614 else
615 {
616 temp[kk] = unsortedarray[jj];
617 ++jj;
618 }
619
620 // increase kk
621 ++kk;
622 }
623
624 // if one half is empty take elements of the other one:
625 while (ii < divlength)
626 {
627 temp[kk] = unsortedarray[ii];
628 ++kk;
629 ++ii;
630 }
631
632 while (jj < n)
633 {
634 temp[kk] = unsortedarray[jj];
635 ++kk;
636 ++jj;
637 }
638
639 // copy sorted temp array back into original data array
640 for (Int_t ll = 0; ll < n; ll++)
641 {
642 unsortedarray[ll] = temp[ll];
643 }
644
645 // free space
646 delete[] temp;
647
648 // return pointer to original data array (which is sorted now)
649 return unsortedarray;
650 }
651}
652
653/** CreateHuffmanTree used by TrainingData to create the binary Huffman tree */
bf7a3243 654AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* AliHLTCOMPHuffmanAltro::CreateHuffmanTree(AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* listroot,AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* lastelement, Int_t n)
c2440081 655{
656 // see header file for class documentation
657 // initialise pointer to go through list
bf7a3243 658 //AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* nextpointer = listroot; // pointer for validation test below
659 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* lastpointer = lastelement;
c2440081 660
661 // build Huffman tree while there are still elements in the list
662 while(n > 2)
663 {
664 // validation test
665 // cout << "current number of remaining list elements n (DEC) = " << n << endl;
bf7a3243 666 // cout << "current abundance of last list element (DEC) = " << lastpointer->fleafcontents.fabundance << endl;
c2440081 667 // cout << "print all list elements from high to low to screen:" << endl;
668 // while(nextpointer != NULL)
669 // {
bf7a3243 670 // cout << nextpointer->fleafcontents.fabundance << endl;
671 // nextpointer = nextpointer->fnext;
c2440081 672 // }
673 // cout << " end of list " << endl;
674
675 // create new tree element from last two entries in orderedarray
bf7a3243 676 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* temptree = new AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct;
9fc6f3ff 677 // error if temptree = NULL
678 if (temptree == NULL)
679 {
680 HLTError("Error! Allocation of Huffman binary tree failed");
681 return NULL;
682 };
c2440081 683
684 // initialise the new element:
bf7a3243 685 temptree->fleafcontents.famplitude = TIMEBINS; //internal nodes mustn't be confused with real amplitudes (from 0 to bitsize)!
c2440081 686
687 // validation test
bf7a3243 688 // cout <<"current abundance of last list element (DEC) = " << lastpointer->fleafcontents.fabundance << endl;
c2440081 689
690 // initialise abundance starting with last element
bf7a3243 691 temptree->fleafcontents.fabundance = lastpointer->fleafcontents.fabundance;
c2440081 692
693 // code assignment small ones get 0, large ones get 1:
bf7a3243 694 lastpointer->fleafcontents.fcode = 0;
c2440081 695
696 // append smallest element on the left and set pointer temptree = parent
bf7a3243 697 temptree->fleft = lastpointer;
698 lastpointer->fparent = temptree;
c2440081 699
700 // go on to second last element and set abundance, code and append on right side of the new element
bf7a3243 701 lastpointer = lastpointer->fprevious;
c2440081 702
703 // validation test
bf7a3243 704 // cout << "current abundance of second last list element (DEC) = " << lastpointer->fleafcontents.fabundance << endl;
c2440081 705
706 cout.flush();
707
bf7a3243 708 temptree->fleafcontents.fabundance += lastpointer->fleafcontents.fabundance;
709 lastpointer->fleafcontents.fcode = 1;
710 temptree->fright = lastpointer;
711 lastpointer->fparent = temptree;
c2440081 712
bf7a3243 713 temptree->fnext = NULL;
714 temptree->fprevious = NULL;
715 temptree->fparent = NULL;
c2440081 716
717 // validation test
bf7a3243 718 // cout << "current abundance of temptree element = sum of leaf abundances (DEC) = " << temptree->fleafcontents.fabundance << endl;
c2440081 719
720 // write temptree at the suitable place according to its abundance in the list
721 // initialise searchpointer to go through list
bf7a3243 722 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* search = listroot;
723 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* sorting = listroot; // pointer from previous element
c2440081 724
bf7a3243 725 // check if listroot[0].fleafcontents.fabundance < temptree.fleafcontents.fabundance,
c2440081 726 // if so, make temptree new root of list
bf7a3243 727 if (temptree->fleafcontents.fabundance > listroot[0].fleafcontents.fabundance)
c2440081 728 {
729 // validation test
bf7a3243 730 // cout << "abundance of new element (DEC) = " << temptree->fleafcontents.fabundance << " is larger than root abundance (DEC) = " << listroot[0].fleafcontents.fabundance << endl;
c2440081 731
732 // temptree = root
bf7a3243 733 temptree->fnext = search;
734 search->fprevious = temptree;
735 //temptree->fprevious = NULL // for first list element is already done!
c2440081 736 listroot = temptree;
737 }
738 else //sort in at the suitable point in the list
739 {
bf7a3243 740 search = listroot->fnext; // go one further than listroot!
c2440081 741
742 while(search != NULL)
743 {
744 // validation test
bf7a3243 745 // cout << "current abundance of searchpointer (DEC) = " << searchpointer->fleafcontents.fabundance << endl;
c2440081 746
747 // if abundance of list entry > abundance of new element, go to next element,
748 // else sort in at that point
bf7a3243 749 if(search->fleafcontents.fabundance > temptree->fleafcontents.fabundance)
c2440081 750 {
751 // validation test
bf7a3243 752 // cout << "abundance of searchpointer (DEC) = " << search->fleafcontents.fabundance << " is larger than temptree abundance (DEC) = " << temptree->fleafcontents.fabundance << endl;
c2440081 753
754 sorting = search; // remember previous element
bf7a3243 755 search = sorting->fnext; // goto next element
c2440081 756 }
757 else
758 {
bf7a3243 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
c2440081 763
764 search = NULL; //stop sorting in
765 }
766 }
767 } //end of sorting in
768
769 // cut the two elements out of the list:
770
bf7a3243 771 lastpointer = lastpointer->fprevious;
772 lastpointer->fnext = NULL;
c2440081 773
774 // validation test
bf7a3243 775 // cout << "cutting out last two list elements, abundance of current last list element is (DEC) = " << lastpointer->fleafcontents.fabundance << endl;
c2440081 776
777 cout.flush();
778
779 // validation test
780 // if(n <= 15)
781 // {
782 // cout << "current list with new (temptree) element sorted in:" << endl;
783
bf7a3243 784 // AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct * showpointer = listroot;
785 // while((showpointer->fnext != NULL) && (showpointer->fleafcontents.fabundance != 0))
c2440081 786 // {
bf7a3243 787 // cout << "amplitude (DEC) = " << showpointer->fleafcontents.famplitude << " abundance (DEC) = " << showpointer->fleafcontents.fabundance << endl;
c2440081 788
bf7a3243 789 // showpointer = showpointer->fnext;
c2440081 790 // }
791
bf7a3243 792 // cout << "amplitude (DEC) = " << showpointer->fleafcontents.famplitude << " abundance (DEC) = " << showpointer->fleafcontents.fabundance << endl;
c2440081 793 // };
794
795 // perform createHuffmanTree with n-1 elements:
796 --n;
797 }
798
799 // termination for n = 2:
800
801 // create new tree element from last two entries
bf7a3243 802 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* temptree = new AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct;
9fc6f3ff 803 // error if temptree = NULL
804 if (temptree == NULL)
805 {
806 HLTError("Error! Pointer to root of Huffman binary tree = NULL");
807 return NULL;
808 };
c2440081 809
810 // initialise the new element:
bf7a3243 811 temptree->fleafcontents.famplitude = TIMEBINS; //internal nodes mustn't be confused with real event names (from 0 to TIMEBINS)!
c2440081 812
813 // validation test
814 // cout << "assemble last two elements to final tree:" << endl;
bf7a3243 815 // cout << "abundance of last list element (DEC) = " << lastpointer->fleafcontents.fabundance << endl;
c2440081 816
817 // initialise abundance starting with last element
bf7a3243 818 temptree->fleafcontents.fabundance = lastpointer->fleafcontents.fabundance;
c2440081 819
820 // code assignment small ones get 0, large ones get 1:
bf7a3243 821 lastpointer->fleafcontents.fcode = 0;
c2440081 822
823 // append smallest element on the left:
bf7a3243 824 temptree->fleft = lastpointer;
825 lastpointer->fparent = temptree;
c2440081 826
827 // validation test
bf7a3243 828 // cout << "abundance of first list element (DEC) = " << listroot->fleafcontents.fabundance << endl;
c2440081 829
830 cout.flush();
831
832 // go on to second last element and set abundance, code and append on right side of the new element
bf7a3243 833 temptree->fleafcontents.fabundance +=listroot->fleafcontents.fabundance;
834 listroot->fleafcontents.fcode = 1;
835 temptree->fright = listroot;
836 listroot->fparent = temptree;
c2440081 837
bf7a3243 838 temptree->fnext = NULL;
839 temptree->fprevious = NULL;
840 temptree->fparent = NULL;
c2440081 841
842 // validation test
bf7a3243 843 // cout << " final abundance of tree root (DEC) = " << temptree->fleafcontents.fabundance << endl;
c2440081 844
c2440081 845 return temptree;
846}
847
848/** HuffmanCode used by TrainingData to create the Huffman code for all leaves of the HuffmanTree */
bf7a3243 849Int_t AliHLTCOMPHuffmanAltro::HuffmanCode(AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* treeroot, AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct* HuffmanCodearray)
c2440081 850{
851 // see header file for class documentation
bf7a3243 852 while ((treeroot->fleft != NULL) || (treeroot->fright != NULL))
c2440081 853 {
854 // define pointer to go through tree
bf7a3243 855 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* finder = treeroot;
c2440081 856
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
bf7a3243 860
861 AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct* tempstruct = new AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct[tempstructsize];
9fc6f3ff 862 if (!tempstruct) return -1;
c2440081 863
864 for(Int_t jj = 0; jj < tempstructsize; jj++)
865 {
bf7a3243 866 tempstruct[jj].fhuffmancode = 0;
c2440081 867 }
868
869 Int_t passednodes = 0;
870
871 // start searching for leaves
872 while (1)
873 {
874 // if finder points at a leaf:
bf7a3243 875 if (finder->fright == NULL && finder->fleft == NULL)
c2440081 876 {
877 //if it is an internal node
bf7a3243 878 if(finder->fleafcontents.famplitude == TIMEBINS)
c2440081 879 {
880 // validation test
bf7a3243 881 // cout << "found internal node with following abundance to delete (DEC) = " << finder->fleafcontents.fabundance << endl;
c2440081 882
883 //go back to parent and delete node with 256
bf7a3243 884 if (finder->fleafcontents.fcode == 0) // node was left one
c2440081 885 {
bf7a3243 886 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* parent = finder->fparent;
887 parent->fleft = NULL;
c2440081 888 }
889 else // node was right one
890 {
bf7a3243 891 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* parent = finder->fparent;
892 parent->fright = NULL;
c2440081 893 }
894
895 break;
896 }
897 else // if it is a leaf
898 {
899 Int_t checkright = 0; // so leaf is left children
900
901 // leaf can also be a right leaf:
bf7a3243 902 if (finder->fleafcontents.fcode == 1)
c2440081 903 {
904 checkright = 1; // if code == 1, leaf is right children
905 };
906
907 // write collected data in the respective array:
908
909 // validation test if amplitudes are correctly found (after being initialised to TIMEBINS+1 in TrainingData()
bf7a3243 910 // HuffmanCodearray[finder->fleafcontents.famplitude].famplitude = finder->fleafcontents.famplitude;
c2440081 911
912 // validation test
bf7a3243 913 // cout << "found leaf with amplitude (DEC) = " << finder->fleafcontents.famplitude << endl;
c2440081 914
bf7a3243 915 HuffmanCodearray[finder->fleafcontents.famplitude].fvalidcodelength = passednodes;
c2440081 916
917 // validation test
bf7a3243 918 // cout << "found leaf with validlength (DEC) = " << HuffmanCodearray[foundleaves].fvalidcodelength << endl;
c2440081 919
920 //write code:
bf7a3243 921 HuffmanCodearray[finder->fleafcontents.famplitude].fhuffmancode = tempstruct[0].fhuffmancode;
c2440081 922
923 // validation test
bf7a3243 924 //cout << "found leaf with code (HEX) = " << hex << HuffmanCodearray[finder->fleafcontents.famplitude].fhuffmancode << dec << endl;
c2440081 925
926 if(passednodes > 64) // if there is more code to write (not usual in normal zero-suppressed data streams!)
927 {
928
bf7a3243 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);
c2440081 930
9fc6f3ff 931 delete[] tempstruct;
c2440081 932 return 1;
933 }
934
935 // validation test
936 // cout << "found leaf written after passed nodes (DEC) = " << passednodes << endl;
937
938 // deleting found leaf from tree
bf7a3243 939 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* parent = finder->fparent; // go one up and set pointer to leaf to zero:
c2440081 940
941 // validation test
bf7a3243 942 // cout << "parent abundance from found leaf (DEC) = " << finder->fleafcontents.fabundance << endl;
c2440081 943
944 if (checkright == 1) // if leaf is right children -> delete right
945 {
bf7a3243 946 parent->fright = NULL;
c2440081 947 }
bf7a3243 948 else //else: delete fleft
c2440081 949 {
bf7a3243 950 parent->fleft = NULL;
c2440081 951 }
952
953 break;
954 }
955 // validation test
956 // cout << " finder pointer at end of deleting the found leaf (DEC) = " << finder << endl;
957 }
958 else // if node is not a leaf
959 {
960 // validation test
bf7a3243 961 //cout << "finder pointer to left child (DEC) = " << finder->fleft << endl;
962 //cout << "finder pointer to right child (DEC) = " << finder->fright << endl;
c2440081 963
bf7a3243 964 if(finder->fleft != NULL)
c2440081 965 {
bf7a3243 966 finder = finder->fleft; // pointer to children
c2440081 967
968 // validation test
bf7a3243 969 //cout << "left child has abundance (DEC) = " << finder->fleafcontents.fabundance << endl;
c2440081 970
971 // shift left to arrange space for new code element which is zero (->left!)
972 // i.e. nothing further needed to create code
973
974 // validation test
bf7a3243 975 //cout << "code for left child is created as (DEC) = " << tempstruct->fhuffmancode << endl;
c2440081 976
977 //problem if passednodes > 63 --> inserting another bit becomes tricky:
978 if(passednodes < 64)
979 {
bf7a3243 980 tempstruct[0].fhuffmancode = tempstruct[0].fhuffmancode << 1;
c2440081 981 }
982 else // error as valid codelength should not exceed 64 bits
983 {
984
985 HLTError("Error! Valid codelength for current encoding process becomes larger than 64 bits, which is not usual for normal input data");
986
9fc6f3ff 987 delete[] tempstruct;
c2440081 988 return 1;
989 }
990
991 // validation test
bf7a3243 992 //cout << "code for left child has been written as (DEC) = " << tempstruct->fhuffmancode << endl;
c2440081 993
994 ++passednodes;
995 }
996 else
997 {
bf7a3243 998 finder = finder->fright; // goto right children
c2440081 999
1000 // validation test
bf7a3243 1001 //cout << "right child has abundance (DEC) = " << finder->fleafcontents.fabundance << endl;
c2440081 1002
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
1005
1006 // validation test
bf7a3243 1007 //cout << "code for right child is created as (DEC) = " << tempstruct->fhuffmancode << endl;
c2440081 1008
1009 //problem if passednodes > 63 --> inserting another bit becomes tricky:
1010 if(passednodes < 64)
1011 {
bf7a3243 1012 tempstruct[0].fhuffmancode = tempstruct[0].fhuffmancode << 1;
1013 tempstruct[0].fhuffmancode = (tempstruct[0].fhuffmancode) | 1;
c2440081 1014 }
1015 else
1016 {
1017
1018 HLTError("Error! Valid codelength for current encoding process becomes larger than 64 bits, which is not usual for normal input data");
1019
1020 }
1021
1022 // validation test
bf7a3243 1023 //cout << "code for right children has been written as (DEC) = " << tempstruct->fhuffmancode << endl;
c2440081 1024
1025 ++passednodes;
1026 } // end of right children search
1027 } // end of no-leaf-search
1028 } // end of while-loop for leaf-search
1029
1030 //freespace
1031 delete[] tempstruct;
1032 } // end of while-loop for tree != root only
1033
1034 // error when there is an amplitude = TIMEBINS in the HuffmanArray
1035 for(int jj = 0; jj < TIMEBINS; jj++)
1036 {
bf7a3243 1037 if(HuffmanCodearray[jj].famplitude == TIMEBINS)
c2440081 1038 {
1039 HLTError("Error! Internal node from Huffman tree in Huffmanarray for 10 bit word (DEC) %i", jj);
1040 };
1041 }
1042
1043 return 0;
1044}
1045
c2440081 1046Int_t AliHLTCOMPHuffmanAltro::TrainingData()
1047{
e3107b54 1048 // fill training data to create the HuffmanCode from a binary tree
1049 int iResult=0;
1050
c2440081 1051 // total number of events counted
1052 Int_t totalnumber = 0;
1053
e3107b54 1054 if (!fpAltroRawStream) return -ENODATA;
1055 fpAltroRawStream->Reset();
c2440081 1056
1057 // initialise required variables for input reading:
1058 AliHLTUInt32_t data10 = 0; // temporary number to read out 10bit word with
c2440081 1059
e3107b54 1060 if (!fTrainingTable && (iResult=InitNewTrainingTable())<=0)
1061 return -iResult;
1062
1063 // read altro data
1064 while (fpAltroRawStream->NextDDL()) {
1065 while (fpAltroRawStream->NextChannel()) {
1066 int iNofBunches=0;
1067 // include payload size in training table
1068 data10=fpAltroRawStream->GetChannelPayloadSize();
1069 //fTrainingTable[(Int_t)(data10)].fabundance += 1;
1070 if (fpAltroRawStream->NextBunch()) {
1071 do {
1072 // include bunch length in training table
1073 int iBunchLen=fpAltroRawStream->GetBunchLength();
1074 data10=iBunchLen;
1075 fTrainingTable[(Int_t)(data10)].fabundance += 1;
1076
1077 // include start time in training table
1078 int iStartTime=fpAltroRawStream->GetStartTimeBin();
1079 data10=iStartTime;
1080 //fTrainingTable[(Int_t)(data10)].fabundance += 1;
1081
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;
1087 }
1088 iNofBunches++;
1089 } while (fpAltroRawStream->NextBunch());
1090 }
c2440081 1091
1092 // increase total number of events
1093 totalnumber += 1;
c2440081 1094 }
e3107b54 1095 }
c2440081 1096
e3107b54 1097 fOutputDataSize = 0;
c2440081 1098
e3107b54 1099 return 0;
c2440081 1100}
1101
1102/** Create Huffman code table out of abundance table filled by training data in DoEvent function of component */
1103Int_t AliHLTCOMPHuffmanAltro::CreateCodeTable()
1104{
1105 // see header file for class documentation
1106 // using merge sort to sort the list: (stable algorithm, quick even in worst case O(nlogn))
bf7a3243 1107 AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct* HuffmanArraySorted = Mergesort(fTrainingTable, TIMEBINS);
c2440081 1108
1109 // abort when there is no pointer to sorted array (error produced in Mergesort function)
1110 if(HuffmanArraySorted == NULL)
1111 {
1112 return 1;
1113 }
1114
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++)
1118 {
bf7a3243 1119 if(HuffmanArraySorted[kk].fabundance < HuffmanArraySorted[kk+1].fabundance)
c2440081 1120 {
bf7a3243 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);
c2440081 1122
1123 return 1;
1124 };
1125 }
1126
1127 // validation test
1128 //cout << "merge sort for training table is now done " << endl;
1129
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)
1134
1135 // check how many 10 bit words are used ("missing channel problem)
bf7a3243 1136 for(UInt_t kk = 0; kk < TIMEBINS; kk++)
c2440081 1137 {
bf7a3243 1138 if((HuffmanArraySorted[kk].fabundance == 0))
c2440081 1139 {
1140 ++zeroentries;
1141 };
1142 }
1143
1144 // -> new array size is "filled"
1145 // validation test
1146 // cout << "number of filled array entries (DEC) = " << filled << endl;
1147
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)
1150 {
bf7a3243 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);
c2440081 1152 }
1153
8bdb460b 1154 // FIXME use auto_ptr, use size of HuffmanArraySorted instead of TIMEBINS
bf7a3243 1155 // initialise leaves of the tree as list (= queue) ofAliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct,
64db5625 1156 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct * HuffmanTreeList = new AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct[filled];
c2440081 1157
1158 // initialise first element
bf7a3243 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;
c2440081 1164
1165 // validation test
1166 // write list to screen
bf7a3243 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;
c2440081 1168
1169 // initialise 1 to filled-2 elements
bf7a3243 1170 UInt_t kk = 1;
c2440081 1171 while(kk < filled-1)
1172 {
bf7a3243 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];
c2440081 1178
1179 // validation test
1180 // write list to screen
bf7a3243 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;
c2440081 1182
1183 kk += 1;
1184 }
1185
1186 // initialise last list entry with next pointer to NULL
bf7a3243 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];
c2440081 1192
1193 // initialise pointer to last list element:
bf7a3243 1194 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* lastelement = &HuffmanTreeList[filled-1];
c2440081 1195
1196 // validation test
1197 // write last element to screen
bf7a3243 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;
c2440081 1199
1200 //use this sorted list to build up the binary tree with root pointer to the beginning:
bf7a3243 1201 AliHLTCOMPHuffmanData::AliHLTCOMPHuffmanTreeDataStruct* root = CreateHuffmanTree(HuffmanTreeList, lastelement, filled);
c2440081 1202
1203 // abort if root = NULL (error already produced in CreateHuffmanTree function)
64db5625 1204 delete [] HuffmanTreeList;
1205
c2440081 1206 if(root == NULL)
1207 {
1208 return 1;
1209 };
1210
1211 // validation test
1212 // cout << "binary tree is now created " << endl;
1213
1214 // create an array for the HuffmanCode data:
bf7a3243 1215 fTranslationTable = new AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct[TIMEBINS];
c2440081 1216
1217 // initialise the array with validcodelengths 0 and codes = 0
98697c64 1218 for(Int_t kk1 = 0; kk1 < TIMEBINS; kk1++)
c2440081 1219 {
1220 // validation test for correct HuffmanCode()
98697c64 1221 // fTranslationTable[kk1].famplitude = TIMEBINS+1; // check if eventnames are written
c2440081 1222
98697c64 1223 fTranslationTable[kk1].famplitude = kk1;
1224 fTranslationTable[kk1].fhuffmancode = 0;
1225 fTranslationTable[kk1].fvalidcodelength = 0;
1226 // fTranslationTable[kk1].morecode = NULL;
c2440081 1227 }
1228
1229 // create HuffmanCode and abort when HuffmanCode produces errors
1230 if(HuffmanCode(root,fTranslationTable) == 1)
1231 {
1232 return 1;
1233 };
1234
1235 // validation test
1236 // cout << "Huffman coding is now done " << endl;
1237
1238 // validation test
1239 // print the Huffman code table to screen
1240 // for(Int_t kk = 0; kk < TIMEBINS; kk++)
1241 // {
bf7a3243 1242 // if (fTranslationTable[kk].fvalidcodelength != 0)
1243 // cout << fTranslationTable[kk].famplitude << " | " << fTranslationTable[kk].fhuffmancode << " | " << fTranslationTable[kk].fvalidcodelength << endl;
c2440081 1244 // }
1245
1246 // findout maximal and minimal codelength and print them out
f0d05e66 1247 UInt_t maxcodelength = fTranslationTable[0].fvalidcodelength;
1248 UInt_t mincodelength = TIMEBINS;
c2440081 1249
98697c64 1250 for (Int_t kk2 = 0; kk2 < TIMEBINS; kk2++)
c2440081 1251 {
98697c64 1252 // if(fTranslationTable[kk2].fvalidcodelength != 0) {cout << kk2 << " | " << fTranslationTable[kk2].fhuffmancode << " | " << fTranslation "Table[kk2].fvalidcodelength << endl;}
c2440081 1253
98697c64 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;};
c2440081 1258 }
1259
1260 // print results to screen
1261 HLTInfo("maximal codelength (DEC) = %i ", maxcodelength);
1262 HLTInfo("minimal codelength (DEC) = %i ", mincodelength);
1263
1264 return 0;
1265}
1266
1267/** TTMergesort used by EntropyDecoding to sort translation table according to validcodelength from low to high */
bf7a3243 1268AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct* AliHLTCOMPHuffmanAltro::TTMergesort(AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct *unsortedarray, Int_t n)
c2440081 1269{
1270 // see heaeder file for class documentation
bf7a3243 1271 //divide array into two halfs: left and right (fleft.size = divlength)
c2440081 1272 Int_t divlength = n >> 1;
1273
1274 if (n==1)
1275 {
1276 // error when unsorted array = NULL
1277 if (unsortedarray == NULL)
1278 {
1279 HLTError("Error! Pointer to final merge sorted code table = NULL");
1280 };
1281
1282 return unsortedarray;
1283 }
1284 else
1285 {
1286 // sort both halfs recursively:
1287 TTMergesort(unsortedarray, divlength); //left half
1288 TTMergesort(&unsortedarray[divlength], n-divlength); //right half
1289
1290 // merge together:
1291 // create temporary result array:
bf7a3243 1292 AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct* temp = new AliHLTCOMPHuffmanCodeData::AliHLTCOMPHuffmanCodeStruct[n];
c2440081 1293
1294 // counters:
1295 Int_t ii, jj, kk;
1296
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;)
1299 {
bf7a3243 1300 if (unsortedarray[ii].fvalidcodelength < unsortedarray[jj].fvalidcodelength)
c2440081 1301 {
1302 temp[kk] = unsortedarray[ii];
1303 ++ii;
1304 }
1305 else
1306 {
1307 temp[kk] = unsortedarray[jj];
1308 ++jj;
1309 }
1310
1311 // increase kk
1312 ++kk;
1313 }
1314
1315 // if one half is empty take elements of the other one:
1316 while (ii < divlength)
1317 {
1318 temp[kk] = unsortedarray[ii];
1319 ++kk;
1320 ++ii;
1321 }
1322
1323 while (jj < n)
1324 {
1325 temp[kk] = unsortedarray[jj];
1326 ++kk;
1327 ++jj;
1328 }
1329
1330 // copy sorted temp array back into original data array
1331 for (Int_t ll = 0; ll < n; ll++)
1332 {
1333 unsortedarray[ll] = temp[ll];
1334 }
1335
1336 // free space
1337 delete[] temp;
1338
1339 // return pointer to original data array (which is sorted now)
1340 return unsortedarray;
1341 }
1342}
1343
1344/** function for the entropy decoding, needed input: code table, input data pointer and size and pointer where to write decoded data */
1345Int_t AliHLTCOMPHuffmanAltro::EntropyDecompression()
1346{
1347 // see heaeder file for class documentation
1348 // validation test
1349 // print translation table to screen
1350 // for(int kk= 0; kk < TIMEBINS; kk++)
1351 // {
bf7a3243 1352 // cout << fTranslationTable[kk].famplitude << " | " << fTranslationTable[kk].fhuffmancode << " | " << fTranslationTable[kk].fvalidcodelength << endl;
c2440081 1353 // }
1354
1355 // sort translation table according to validcodelengths from low to high (codes that occur often are found quickly)
1356 fTranslationTable = TTMergesort(fTranslationTable, TIMEBINS);
1357
1358 // validation test
1359 // print merge sorted translation table to screen
1360 // for(int kk= 0; kk < TIMEBINS; kk++)
1361 // {
bf7a3243 1362 // cout << fTranslationTable[kk].famplitude << " | " << fTranslationTable[kk].fhuffmancode << " | " << fTranslationTable[kk].fvalidcodelength << endl;
c2440081 1363 // }
1364
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!
1367
1368 // initialise reading pointer on compressed data
1369 AliHLTUInt64_t* pointerprop = (AliHLTUInt64_t*)fPointer2InData;
1370
1371 // initialise writing pointer for decompressed output array
1372 AliHLTUInt64_t* pointeroutputprop = (AliHLTUInt64_t*) fPointer2OutData;
1373
1374 // outputdata size initialised
1375 fOutputDataSize = 0;
1376
1377 // validation test
1378 // cout << "input data size of encoded data (DEC) = " << fInputDataSize << endl;
1379 // cout << "output data size of decoded data (DEC) = " << fOutputDataSize << endl;
1380
1381 // create temporary word to read out 1 bit from, maximal length: 64 bits */
1382 AliHLTUInt64_t codedata = 0;
bf7a3243 1383 UInt_t codedatalength = 0;
c2440081 1384
1385 // number of 32-bit trailer and common data header words:
bf7a3243 1386 UInt_t headerwords = 8;
1387 UInt_t header64 = headerwords >> 1;
c2440081 1388
1389 // initialise counter variables for input array:
bf7a3243 1390 UInt_t idxwd = header64; // due to 8*32 = 4*64 bit header words
1391 UInt_t bitpswd = 0;
c2440081 1392
1393 // initialise counter variables for output array:
1394 UInt_t idxoutwd = header64; // due to 8*32 = 4*64 bit header words
bf7a3243 1395 // UInt_t idx10out = 0; // only used for validation test
c2440081 1396 UInt_t bitpsoutwd = 0;
1397
1398 // write header to output (two words input header in one word output header):
1399 UInt_t head64cntr = 0;
1400
1401 while(head64cntr < header64)
1402 {
1403 pointeroutputprop[head64cntr] = pointerprop[head64cntr];
1404
1405 // validation test
1406 //cout << "header line in output stream (HEX) = " << hex << pointeroutputprop[head64cntr] << dec << endl;
1407
1408 ++head64cntr;
1409 }
1410
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);
1416
1417 --lastfullline;
1418 --lastcodeline;
1419
1420 if (lastbit == 0)
1421 {
1422 lastbit = 64;
1423 }
1424
1425 // initialise last valid bit position and trailer array
1426 AliHLTUInt32_t lastvalidbitpos = 0;
1427 AliHLTUInt64_t* trailer = new AliHLTUInt64_t[fNrcuTrailerwords];
9fc6f3ff 1428 if (!trailer) return -1;
c2440081 1429
1430 // validation test
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;
1437
1438 // get last valid bit position (first 32 bit word in first trailer line after code
1439 // and trailerwords
1440 if (fNrcuTrailerwords < 3) // then lastfullline = only trailerline
1441 {
1442 lastvalidbitpos = (pointerprop[lastfullline] >> 32);
1443
1444 // first trailerword
1445 trailer[0] = ((pointerprop[lastfullline] << 32 ) >> 32);
1446
1447 // second trailerword
1448 if(fNrcuTrailerwords == 2)
1449 {
1450 trailer[1] = ((pointerprop[lastfullline+1] << 32) >> 32);
1451 };
1452 }
1453 else
1454 {
1455 lastvalidbitpos = (pointerprop[lastfullline-1] >> 32);
1456
1457 // first trailerword
1458 trailer[0] = ((pointerprop[lastfullline-1] << 32 ) >> 32);
1459
1460 //second trailerword
1461 trailer[1] = (pointerprop[lastfullline] >> 32);
1462
1463 // third trailerword
1464 trailer[2] =((pointerprop[lastfullline] << 32 ) >> 32);
1465 }
1466
1467 // validation test
1468 // cout << "last valid bit position (DEC) = " << lastvalidbitpos << endl;
1469
1470 // warning if one of the trailer words is zero:
bf7a3243 1471 for (UInt_t kk = 0; kk < fNrcuTrailerwords; kk++)
c2440081 1472 {
1473 if(trailer[kk] == 0)
1474 {
bf7a3243 1475 HLTWarning("Warning! Trailer word %i is zero",kk+1);
c2440081 1476 };
1477 }
1478
1479 // validation test
1480 // print trailer array to screen
1481 // for(Int_t ii=0; ii < fNrcuTrailerwords; ii++)
1482 // {
1483 // cout << "trailerword " << ii+1 << " after getting whole trailer (HEX) = " << hex << trailer[ii] << dec << endl;
1484 // }
1485
1486 // find minmal validcodelength from first entry of translation table and
1487 // read in minimal validcodelength bits if codedata is zero...
bf7a3243 1488 UInt_t minimalcodelength = fTranslationTable[0].fvalidcodelength;
c2440081 1489
1490 // validation test
1491 // cout << "minimal codelength (DEC) = " << minimalcodelength << endl;
1492
1493 Int_t readnewcode = 1; // read new code = 1; go on with old code = 0
1494
1495 // start decoding
1496 // NEW (bitpswd >= lastvalidbitpos) instead of (bitpswd > lastvalidbitpos)
1497 while (!((idxwd >= lastcodeline) && (bitpswd >= lastvalidbitpos)) )
1498 {
1499 if((idxwd == lastcodeline+1) && (bitpswd == 0)) break; // abortion when lastvalidbitpos = 64
1500
1501 if (codedatalength < 64) // if codedata can still get one further bit
1502 {
1503 // if new code word is read before end position
1504 if((readnewcode == 1) && !((idxwd >= lastcodeline) && (bitpswd + minimalcodelength > lastvalidbitpos)))
1505 {
1506 // codedata gets next bits from encoded input file:
1507 codedata <<= minimalcodelength; //shift bits left
1508
1509 if (bitpswd + minimalcodelength < 65) // all bits in the same line
1510 {
1511 codedata |= ((pointerprop[idxwd] << bitpswd)) >> (64 - minimalcodelength); //append bits from input file to the right
1512 }
1513 else // some of this bits in the next line
1514 {
1515 // append bits of current line to the right end of codedata
1516 codedata |= (((pointerprop[idxwd] << bitpswd)) >> (bitpswd)) << (minimalcodelength - 64 + bitpswd);
1517
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))
1520 }
1521
1522 codedatalength += minimalcodelength;
1523
1524 // new code is read, set readnewcode back to 0 again
1525 readnewcode = 0;
1526
1527 // go and get next input bit
1528 bitpswd += minimalcodelength;
1529 }
1530 else
1531 {
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
1535
1536 ++codedatalength;
1537
1538 // go and get next input bit
1539 ++bitpswd;
1540 }
1541
1542 // go and get next input bit
1543 if(bitpswd > 63)
1544 {
1545 ++idxwd;
1546 bitpswd = bitpswd & 0x3F;
1547 };
1548
1549 // compare if new codedata is in translation table:
bf7a3243 1550 for(UInt_t kk = 0; kk < TIMEBINS; kk++)
c2440081 1551 {
1552 // stopping when current codedatalength smaller than lookup validcodelength (i.e. current code not in table, read next bit)
bf7a3243 1553 if(fTranslationTable[kk].fvalidcodelength > codedatalength)
c2440081 1554 {
1555 break;
1556 };
1557
bf7a3243 1558 if(fTranslationTable[kk].fhuffmancode == codedata) //lookup bit pattern
c2440081 1559 {
bf7a3243 1560 if(fTranslationTable[kk].fvalidcodelength == codedatalength) //lookup correct codelength
c2440081 1561 {
1562 // validation test
1563 // if( idxoutwd >= 2636)
1564 //{
bf7a3243 1565 // cout << "write 10 bit word to decoded output (DEC) = " << fTranslationTable[kk].famplitude << endl;
c2440081 1566 // cout << "current idxwd (DEC) = " << idxwd << endl;
1567 // cout << "current idxoutwd (DEC) = " << idxoutwd << endl;
1568 //}
1569 if(bitpsoutwd + 10 < 65) //fits in old line
1570 {
1571 // valdidation test for end of decoded data
1572 // print all relevant quantities to screen
1573 //if(idxwd > 2635)
1574 // {
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;
bf7a3243 1582 // cout << "10 bit value (HEX) = " << hex << fTranslationTable[kk].famplitude << dec << endl;
c2440081 1583 // }
1584
bf7a3243 1585 pointeroutputprop[idxoutwd] |= ((AliHLTUInt64_t)(fTranslationTable[kk].famplitude)) << bitpsoutwd;
c2440081 1586
1587 // validation test
1588 // if (idxoutwd > 362880)
1589 // {
1590 // cout << "updated output line (HEX) = " <<hex << pointeroutputprop[idxoutwd] <<dec << endl;
1591 // }
1592
1593 // goto next 10-bits output position
1594 bitpsoutwd += 10;
1595
1596 if(bitpsoutwd == 64) {bitpsoutwd = 0; ++idxoutwd;};
1597
1598 }
1599 else //needs start of new line
1600 {
1601
bf7a3243 1602 pointeroutputprop[idxoutwd] |= ((AliHLTUInt64_t)(fTranslationTable[kk].famplitude)) << (bitpsoutwd);
c2440081 1603
1604 ++idxoutwd; //start new line
1605
1606 // validation test
1607 // if(idxwd > 2635)
1608 //{
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;
bf7a3243 1616 // cout << "10 bit value (HEX) = " << hex << fTranslationTable[kk].famplitude << dec << endl;
c2440081 1617 //}
1618
1619 // write next line
bf7a3243 1620 AliHLTUInt64_t buffer = fTranslationTable[kk].famplitude;
c2440081 1621 buffer >>= (64 - bitpsoutwd);
1622
1623 pointeroutputprop[idxoutwd] = buffer;
1624
1625 // validation test
1626 // if (idxoutwd > 362880)
1627 // {
1628 // cout << "new line (HEX) = " << hex << pointeroutputprop[idxoutwd] << dec << endl;
1629 // }
1630
1631 // go to next bit position
1632 bitpsoutwd -= 54;
1633 }
1634
1635 // set buffers to zero again
1636 codedata = 0;
1637 codedatalength = 0;
1638
1639 // prepare codedata to read new code word
1640 readnewcode = 1;
1641
bf7a3243 1642 // validation test
1643 // ++idx10out;
1644
c2440081 1645 // go on with next code bits from input
1646 break;
1647 };
1648 };
1649 }
1650 }
1651 else // if *morecode is used
1652 {
1653
1654 HLTError("Error! Valid codelength for current decoding is larger than 64 bits, error in recognising the correct code");
1655
9fc6f3ff 1656 delete [] trailer;
c2440081 1657 return 1;
1658
1659 }
1660 }
1661
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)
1665
1666 // validation test
1667 // cout << "bit position after decoding (DEC) = " << bitpsoutwd << endl;
1668 // cout << "line position after decoding (DEC) = " << idxoutwd << endl;
1669
1670 // warning if byte position is not 8-bits aligned
1671 if ((bitpsoutwd & 0x07) != 0 )
1672 {
bf7a3243 1673 HLTWarning("Warning! Bit position after decoding %i is not aligned to 8 bits", bitpsoutwd);
c2440081 1674 };
1675
1676 if(bitpsoutwd + 32 < 65) // trailer fits in current line, append on the right
1677 {
1678 pointeroutputprop[idxoutwd] <<= 32;
1679
1680 pointeroutputprop[idxoutwd] |= trailer[0];
1681
1682 bitpsoutwd += 32;
1683 }
1684 else
1685 {
1686 pointeroutputprop[idxoutwd] <<= 64 - bitpsoutwd;
1687 pointeroutputprop[idxoutwd]|= (trailer[0] >> (bitpsoutwd - 32));
1688
1689 // go to next line
1690 ++idxoutwd;
1691
1692 // get rid of upper, already written bits
1693 trailer[0] <<= 96 - bitpsoutwd;
1694 trailer[0] >>= 96 - bitpsoutwd;
1695
1696 pointeroutputprop[idxoutwd] = trailer[0]; // write lower bits to next line
1697
1698 bitpsoutwd -= 32;
1699 }
1700
1701 if(fNrcuTrailerwords > 1)
1702 {
1703
1704 if(bitpsoutwd == 64)
1705 {
1706 bitpsoutwd = 0;
1707 ++idxoutwd;
1708 }
1709
af2ed151 1710 for(UInt_t ii = 1; ii < fNrcuTrailerwords; ii++)
c2440081 1711 {
1712 // write second trailer to output data
1713 if(bitpsoutwd + 32 < 65) // trailer fits in current line, append on the right
1714 {
1715 pointeroutputprop[idxoutwd] <<= 32;
1716
1717 pointeroutputprop[idxoutwd] |= trailer[ii];
1718
1719 bitpsoutwd += 32;
1720
1721 if(bitpsoutwd == 64)
1722 {
1723 bitpsoutwd = 0;
1724 ++idxoutwd;
1725 }
1726 }
1727 else
1728 {
1729 pointeroutputprop[idxoutwd] <<= 64 - bitpsoutwd;
1730 pointeroutputprop[idxoutwd]|= (trailer[ii] >> (bitpsoutwd - 32));
1731
1732 // go to next line
1733 ++idxoutwd;
1734
1735 // get rid of upper, already written bits
1736 trailer[ii] <<= 96 - bitpsoutwd;
1737 trailer[ii] >>= 96 - bitpsoutwd;
1738
1739 pointeroutputprop[idxoutwd] = trailer[ii]; // write lower bits to next line
1740
1741 bitpsoutwd -= 32;
1742 }
1743 }
1744 }
1745 // validation test
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;
1750
1751 // write trailer to decoded output
1752
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) );
1758
9fc6f3ff 1759 delete [] trailer;
c2440081 1760 // error and abort when output data size smaller than input data size (impossible when decompressing)
1761 if(fOutputDataSize < fInputDataSize)
1762 {
1763 HLTError("Error! Data size for decompressed output stream (bytes) %i is smaller than compressed input data size (bytes) %i", fOutputDataSize, fInputDataSize);
1764
1765 return 1;
1766 };
1767
1768 // validation test
1769 // cout << "output data size (DEC) = " << fOutputDataSize << endl;
1770
1771 return 0;
1772}
1773
e3107b54 1774Int_t AliHLTCOMPHuffmanAltro::CalcEntropy(const AliHLTCOMPHuffmanOccurrenceData::AliHLTCOMPHuffmanDataStruct* occurrencetable)
c2440081 1775{
e3107b54 1776 // calculate entropy of 10 bit values
1777 if (!occurrencetable) occurrencetable=fTrainingTable;
1778 if (!occurrencetable) return -ENODATA;
1779
1780 int totalnumber=accumulate(occurrencetable, occurrencetable+TIMEBINS, int(0), AliHLTCOMPHuffmanOccurrenceSum());
1781 if (totalnumber<1) {
1782 HLTWarning("can not calculate entropy from empty table");
1783 fEntropy=0.0;
1784 return 0;
1785 }
1786
1787 double entropy=0.0;
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);
1793 }
c2440081 1794
e3107b54 1795 fEntropy=entropy;
c2440081 1796 return 0;
1797}
1798
1799/* CopyData is just a function for performance testing */
1800Int_t AliHLTCOMPHuffmanAltro::CopyData()
1801{
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;
1807
1808 //first output word has to be initialised
1809 pointeroutprop[0] = 0;
1810
1811 fOutputDataSize = fInputDataSize;
1812
1813 // initialise required variables for input reading:
1814 AliHLTUInt32_t data10 = 0; // temporary number to read out 10bit word with
bf7a3243 1815 UInt_t idxwd = 8;
1816 UInt_t idx10 = 0;
1817 UInt_t bitpswd = 0;
c2440081 1818
1819 // number of 32-bit trailer and common data header words:
1820 // (taken out of compression!)
bf7a3243 1821 // UInt_t headerwords = 8;
c2440081 1822
1823 // initialise required variables for ouput creation:
bf7a3243 1824 UInt_t idxoutwd = 0;
c2440081 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
1827
1828 UInt_t endNdx = (fInputDataSize>>2)-fNrcuTrailerwords;
1829
1830 // start reading and encoding input data (which are 10 bit words):
1831 while (idxwd < endNdx)
1832 {
1833 // write input data in temp and cut out 10 bits with mask 0x3FF
1834 data10 = (pointer2InData[idxwd] >> bitpswd ) & 0x3FFU;
1835
1836 // validation test
1837 //cout << "current 10 bits word (DEC) = " << data10 << endl;
1838
1839 // if number of bits left in read input less than ten, get remaining bits from next 32bit word
1840 if(bitpswd > 21)
1841 {
1842 data10 |= (pointer2InData[idxwd + 1]) << (32 - bitpswd);
1843 data10 &= 0x3FFU;
1844 };
1845
1846 // validation test
1847 // print first 10 bits words to screen
1848 // if (idx10 < 100)
1849 // {
1850 // cout << "read data: " << hex << data10 << dec << endl;
1851 // };
1852
1853 // write data to 32 bit output:
1854 pointeroutprop[idxoutwd] |= (data10 << bitpswd);
1855
1856 if(bitpswd > 21)
1857 {
1858 pointeroutprop[idxoutwd + 1] = (data10 >> (32 - bitpswd));
1859 }
1860
1861 // validation test
1862 // cout << "next bitpswd (DEC) = " << bitpswd << endl;
1863
1864 ++idx10; // go on reading 10 bit word
1865
1866 // index word reads position of 32bit word in input array
1867 idxoutwd = (idx10 * 10);
1868 bitpswd = idxoutwd & 0x1F;
1869 idxoutwd >>= 5;
1870 idxwd = idxoutwd+8;
1871 // bit position word reads position in 32bit word when 10 bits are read out
1872 }
1873
1874 // validation test
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;
1878
1879 return 0;
1880}
e3107b54 1881
1882void AliHLTCOMPHuffmanAltro::Print(Option_t* option) const
1883{
1884 // print content
1885
1886 if (strcmp(option, "trainingtable")==0) {
1887 // print fTrainingTable to screen (non-zero entries only):
1888 if (!fTrainingTable) {
1889 cout << "no training table" << endl;
1890 return;
1891 }
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;
1895 }
1896 return;
1897 }
1898
1899 if (strcmp(option, "translationtable")==0) {
1900 // print fTranslationTable to screen (non-zero entries only):
1901 if (!fTranslationTable) {
1902 cout << "no translation table" << endl;
1903 return;
1904 }
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;
1908 }
1909 return;
1910 }
1911
8bdb460b 1912 if (strcmp(option, "entropy")==0) {
1913 cout << "Calculated entropy = " << fEntropy << endl;
1914 return;
1915 }
e3107b54 1916}