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