1 /**************************************************************************
2 * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 ////////////////////////////////////////////////
17 // Huffman classes for set:TPC //
18 ////////////////////////////////////////////////
19 //This file contains two classes and it implements
20 //the Huffman algorithm for creating tables
21 //used in the compression phase.
22 //The class AliTPCHNode represents a node of the Huffman tree, while
23 //the class AliTPCHTable represents a compression table
25 #include <TObjArray.h>
26 #include <Riostream.h>
28 #include "AliTPCBuffer160.h"
29 #include "AliTPCHuffman.h"
33 AliTPCHNode::AliTPCHNode(){
39 //////////////////////////////////////////////////////////////////////////////
41 AliTPCHNode::AliTPCHNode(Int_t sym, Double_t freq){
42 //Standard constructor
49 //////////////////////////////////////////////////////////////////////////////
51 AliTPCHNode::AliTPCHNode(const AliTPCHNode &source){
53 if(&source == this) return;
54 this->fSymbol = source.fSymbol;
55 this->fFrequency = source.fFrequency;
56 this->fLeft = source.fLeft;
57 this->fRight = source.fRight;
61 //////////////////////////////////////////////////////////////////////////////
63 AliTPCHNode& AliTPCHNode::operator=(const AliTPCHNode &source){
65 if(&source == this) return *this;
66 this->fSymbol = source.fSymbol;
67 this->fFrequency = source.fFrequency;
68 this->fLeft = source.fLeft;
69 this->fRight = source.fRight;
73 //////////////////////////////////////////////////////////////////////////////
75 Int_t AliTPCHNode::Compare(const TObject *obj)const{
76 //Function called by Sort method of TObjArray
77 AliTPCHNode *node=(AliTPCHNode *)obj;
78 Double_t f=fFrequency;
79 Double_t fo=node->fFrequency;
81 else if (f>fo) return -1;
85 //////////////////////////////////////////////////////////////////////////////
86 //////////////////////////////////////////////////////////////////////////////
87 //////////////////////////////////////////////////////////////////////////////
89 ClassImp(AliTPCHTable)
91 AliTPCHTable::AliTPCHTable(){
101 //////////////////////////////////////////////////////////////////////////////
103 AliTPCHTable::AliTPCHTable(Int_t size){
106 fCodeLen = new UChar_t[fSize];
107 fCode = new Double_t[fSize];
108 fHNodes = new TObjArray;
112 fSym= new Short_t[fSize];
113 for (Short_t i=0;i<fSize;i++) {
119 //////////////////////////////////////////////////////////////////////////////
121 AliTPCHTable::AliTPCHTable(const AliTPCHTable &source){
123 if(&source == this) return;
124 this->fSize = source.fSize;
125 this->fCodeLen = source.fCodeLen;
126 this->fCode = source.fCode;
127 this->fSym = source.fSym;
128 this->fHNodes = source.fHNodes;
129 this->fNnodes = source.fNnodes;
130 this->fNum=source.fNum;
131 this->fVerbose=source.fVerbose;
135 //////////////////////////////////////////////////////////////////////////////
137 AliTPCHTable& AliTPCHTable::operator=(const AliTPCHTable &source) {
138 //Assignment operator
139 if(&source == this) return *this;
140 this->fSize = source.fSize;
141 this->fCodeLen = source.fCodeLen;
142 this->fCode = source.fCode;
143 this->fSym = source.fSym;
144 this->fHNodes = source.fHNodes;
145 this->fNnodes = source.fNnodes;
146 this->fNum=source.fNum;
147 this->fVerbose=source.fVerbose;
151 //////////////////////////////////////////////////////////////////////////////
153 AliTPCHTable::~AliTPCHTable(){
156 cout<<"HTable destructor !\n";
157 if (fCodeLen) delete[] fCodeLen;
158 if (fCode) delete [] fCode;
160 fHNodes->Delete(); //Clear out the collection and deletes the removed objects
165 //////////////////////////////////////////////////////////////////////////////
167 void AliTPCHTable::SetCodeLen(UChar_t len,Int_t val){
168 //Sets codelength of "val" to the variable "len"
173 //////////////////////////////////////////////////////////////////////////////
175 void AliTPCHTable::SetCode(Double_t code,Int_t val){
176 //Sets the binary code of the variable "val"
181 //////////////////////////////////////////////////////////////////////////////
183 void AliTPCHTable::PrintTable()const{
184 //This method prints a table
185 cout<<"Table for Huffman coding\n";
186 cout<<" Symbol| Code | Length \n";
187 for (Int_t i=0;i<fSize;i++){
189 cout.width(6);cout<<fSym[i];
190 cout.width(3);cout<<"|";
191 cout.width(6);cout<<hex<<(ULong_t)fCode[i]<<dec;
192 cout.width(5);cout<<"|";
193 cout.width(6);cout<<(ULong_t)fCodeLen[i]<<endl;
198 //////////////////////////////////////////////////////////////////////////////
200 Bool_t AliTPCHTable::SpanTree(AliTPCHNode *start, ULong_t code, UChar_t len){
201 //Hoffman codes are generated spanning the Huffman tree
202 //In an Huffman tree any internal node has always two children
203 AliTPCHNode * visited;
205 Int_t idx=visited->GetSymbol();
206 if (!visited->GetLeft()) {
211 SpanTree(visited->GetLeft(), code << 1, len + 1);
212 SpanTree(visited->GetRight(), code << 1 | 0x0001, len + 1);
216 //////////////////////////////////////////////////////////////////////////////
218 void AliTPCHTable::ResetHNodes(){
219 //Reset number of HNodes and the HNodes array
220 if (fHNodes) fHNodes->Clear();
221 if (fNnodes) fNnodes=0;
224 //////////////////////////////////////////////////////////////////////////////
226 void AliTPCHTable::ClearTable(){
228 memset(fCodeLen,0,sizeof(UChar_t)*fSize);
229 memset(fCode,0,sizeof(Double_t)*fSize);
232 //////////////////////////////////////////////////////////////////////////////
234 Int_t AliTPCHTable::GetFrequencies(const char *fname){
235 //It fills the "fCode" array with the frequencies of the symbols read from the file
236 AliTPCBuffer160 buff(fname,0);
237 ULong_t numberOfWords=0;
239 while((val=buff.GetNext())!=-1){
244 cout<<"Total number of words: "<<numberOfWords<<endl;
245 //Print out the frequencies
247 for (Int_t i=0;i<fSize;i++){
248 if (fCode[i])cout<<"Symbol: "<<i<<" Freq: "<<fCode[i]<<endl;
255 Int_t AliTPCHTable::SetValFrequency(const Int_t Val,Double_t Value){
256 //This method sets to "Value" the frequency of the symbol "Val"
262 //////////////////////////////////////////////////////////////////////////////
264 Int_t AliTPCHTable::SetFrequency(const Int_t Val){
265 //It increments by one the frequency of the symbol "Val" whose frequency is
266 //stored in the fCode array
272 //////////////////////////////////////////////////////////////////////////////
274 Int_t AliTPCHTable::NormalizeFrequencies(){
275 //This method normalized the frequencies
276 //Frequencies normalization
278 for (Int_t i=0; i< fSize; i++) {
282 cout<<"Frequency sum: "<<sum<<endl;
285 for (Int_t i=0; i< fSize; i++) {
287 if ((fCode[i]!=0.) && (fCode[i]<10e-20))cout<<"Frequency value very small !!! "<<fCode[i]<<endl;
292 //////////////////////////////////////////////////////////////////////////////
293 Int_t AliTPCHTable::StoreFrequencies(const char *fname)const{
294 //It stores the frequencies in a text file
295 ofstream ftxt(fname);
296 for (Int_t i=0;i<fSize;i++){
297 ftxt<<fCode[i]<<endl;
303 //////////////////////////////////////////////////////////////////////////////
305 void AliTPCHTable::CompleteTable(Int_t k){
306 //According to the kind of table (0..4) it associates a dummy frequency (1) to
307 //every symbols whose real frequency is zero, in a given range 0..max
325 for(Int_t i=0;i<max;i++){
326 if(fCode[i]==0.0)fCode[i]=val;
331 //////////////////////////////////////////////////////////////////////////////
333 Double_t AliTPCHTable::GetEntropy()const{
334 //This method calculates the value of the entropy
337 for (Int_t i=0;i<fSize;i++){
339 prob=fCode[i]/(Double_t)fNum;
340 entropy+=prob*(TMath::Log2(prob));
346 //////////////////////////////////////////////////////////////////////////////
348 Int_t AliTPCHTable::BuildHTable(){
349 //It builds a Huffman tree
350 if(GetWordsNumber()){
351 for (Int_t i=0; i< fSize; i++) {
354 //cout<< "Symbol:"<<i<<" Freq:"<<fCode[i]<<endl;
355 fHNodes->Add(new AliTPCHNode(i,fCode[i]));
358 Int_t nentries=fHNodes->GetEntriesFast();
359 //cout<<"Number of symbols: "<<nentries<<endl;
360 Int_t nindex=nentries-1;
362 fHNodes->Sort(nindex+1);
363 AliTPCHNode *aux = new AliTPCHNode(0,0);
364 AliTPCHNode *node= (AliTPCHNode*)fHNodes->UncheckedAt(nindex-1);
365 AliTPCHNode *node1= (AliTPCHNode*)fHNodes->UncheckedAt(nindex);
368 aux->SetRight(node1);
369 aux->SetFrequency(node->GetFrequency() + node1->GetFrequency());
370 fHNodes->RemoveAt(nindex-1);
371 fHNodes->AddAt(aux,nindex-1);
375 AliTPCHNode *start= (AliTPCHNode*)fHNodes->UncheckedAt(0);
379 cout<<"Table contains 0 elements\n";
383 //////////////////////////////////////////////////////////////////////////////