]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTDataDeflaterHuffman.cxx
adding USE_DLOPEN option for HLT
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTDataDeflaterHuffman.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Thorsten Kollegger <kollegge@ikf.uni-frankfurt.de>    *
8 //*                  for The ALICE HLT Project.                            *
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   AliHLTDataDeflaterHuffman.cxx
20 /// @author Thorsten Kollegger, Matthias Richter
21 /// @date   2011-08-10
22 /// @brief  Deflater implementation using huffman code
23
24 #include "AliHLTDataDeflaterHuffman.h"
25 #include "AliHLTHuffman.h"
26 #include "TObjArray.h"
27 #include "TList.h"
28 #include "TString.h"
29 #include "TFile.h"
30 #include <memory>
31 #include <algorithm>
32 #include <iostream>
33
34 /** ROOT macro for the implementation of ROOT specific class methods */
35 ClassImp(AliHLTDataDeflaterHuffman)
36
37 AliHLTDataDeflaterHuffman::AliHLTDataDeflaterHuffman(bool bTrainingMode)
38   : AliHLTDataDeflater()
39   , fReferenceLength()
40   , fHuffmanCoders()
41   , fHuffmanCoderList(NULL)
42   , fTrainingMode(bTrainingMode)
43 {
44   // see header file for class documentation
45   // or
46   // refer to README to build package
47   // or
48   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
49   if (bTrainingMode) {
50     HLTInfo("using DataDeflaterHuffman in training mode");
51   }
52 }
53
54 AliHLTDataDeflaterHuffman::~AliHLTDataDeflaterHuffman()
55 {
56   // destructor
57   if (fHuffmanCoderList) delete fHuffmanCoderList;
58   fHuffmanCoderList=NULL;
59
60   Clear();
61 }
62
63 int AliHLTDataDeflaterHuffman::AddParameterDefinition(const char* name, unsigned bitLength, unsigned refLength)
64 {
65   /// search a parameter definition in the decoder configuration, and set the index
66   /// array, return reference id
67   if (IsTrainingMode())
68     return AddTrainingParameter(name, bitLength);
69
70   if (!name) return -EINVAL;
71   if (!fHuffmanCoderList) return -ENODEV;
72   TObject* pObj=fHuffmanCoderList->FindObject(name);
73   if (!pObj) {
74     HLTError("can not find decoder of id '%s'", name);
75     return -ENOENT;
76   }
77   AliHLTHuffman* pHuffman=dynamic_cast<AliHLTHuffman*>(pObj);
78   if (!pHuffman) {
79     HLTError("object %s has wrong type, expected AliHLTHuffman", name);
80     return -EBADF;
81   }
82   if (pHuffman->GetMaxBits()!=bitLength) {
83     HLTError("mismatch in bitlengt: can not use decoder %s of length %d for encoding of %d bits", pHuffman->GetName(), pHuffman->GetMaxBits(), bitLength);
84     return -EPERM;
85   }
86
87   fReferenceLength.push_back(refLength);
88   fHuffmanCoders.push_back(pHuffman);
89
90   int memberId=fHuffmanCoders.size()-1;
91   if (DoStatistics()) {
92     AddHistogram(memberId, name, bitLength);
93   }
94
95   return memberId;
96 }
97
98 int AliHLTDataDeflaterHuffman::InitDecoders(TList* decoderlist)
99 {
100   /// init list of decoders
101   /// expects to be an external pointer, valid throughout the livetime of
102   /// the instance
103   if (!decoderlist) return -EINVAL;
104   if (!fHuffmanCoderList) {
105     fHuffmanCoderList=new TList;
106   } else {
107     if (fHuffmanCoderList->GetEntries()>0 && fHuffmanCoderList->IsOwner()) {
108       HLTWarning("list of decoders owns already %d object(s), but disabling ownership now because of new external pointers");
109     }
110   }
111   if (!fHuffmanCoderList) return -ENOMEM;
112   fHuffmanCoderList->SetOwner(kFALSE);
113   TIter next(decoderlist);
114   TObject* pObj=NULL;
115   while ((pObj=next())!=NULL) {
116     if (dynamic_cast<AliHLTHuffman*>(pObj)==NULL) continue;
117     if (fHuffmanCoderList->FindObject(pObj->GetName())) {
118       HLTError("duplicate entry of name '%s'", pObj->GetName());
119       return -EEXIST;
120     }
121     fHuffmanCoderList->Add(pObj);
122   }
123
124   return fHuffmanCoderList->GetEntries();
125 }
126
127 bool AliHLTDataDeflaterHuffman::OutputParameterBits( int memberId, AliHLTUInt64_t const & value )
128 {
129   // write huffman encoded bit pattern of a member to the current byte and position
130   if (IsTrainingMode())
131     return AddTrainingValue(memberId, value);
132
133   if (memberId>=(int)fHuffmanCoders.size()) {
134     return false;
135   }
136
137   AliHLTUInt64_t length = 0;
138   const std::bitset<64>& v=fHuffmanCoders[memberId]->Encode((value>fHuffmanCoders[memberId]->GetMaxValue())?fHuffmanCoders[memberId]->GetMaxValue():value, length);
139   //cout << fHuffmanCoders[memberId]->GetName() << " value " << value << ": code lenght " << length << " " << v << endl;
140   if (DoStatistics()) {
141     float weight=0.0;
142     unsigned parameterLength=fHuffmanCoders[memberId]->GetMaxBits();
143     if (memberId<(int)fReferenceLength.size() && fReferenceLength[memberId]>0)
144       parameterLength=fReferenceLength[memberId];
145     if (parameterLength>0) {
146       weight=length;
147       weight/=parameterLength;
148     }
149     FillStatistics(memberId, value, length, weight);
150   }
151
152   if (length>0) {
153     return OutputBits(v, length);
154   }
155
156   return false;
157 }
158
159 int AliHLTDataDeflaterHuffman::AddTrainingParameter(const char* name, unsigned bitLength)
160 {
161   /// add a parameter definition for huffman training
162
163   /// returns index in the array
164   if (!fHuffmanCoderList) {
165     fHuffmanCoderList=new TList;
166     if (!fHuffmanCoderList) return -ENOMEM;
167     // always set ownership for the new list since it is supposed to
168     // contain only internal pointers
169     fHuffmanCoderList->SetOwner();
170   } else if (!fHuffmanCoderList->IsOwner()) {
171     // not sure about the pointers which are already in the list
172     if (fHuffmanCoderList->GetEntries()>0) {
173       HLTWarning("skip setting ownership because list contains already %d object(s), possible memory leak at cleanup");
174     } else {
175       fHuffmanCoderList->SetOwner();
176     }
177   }
178   AliHLTHuffman* pHuffman=new AliHLTHuffman(name, bitLength);
179   if (!pHuffman) return -ENOMEM;
180   fHuffmanCoderList->Add(pHuffman);
181
182   fHuffmanCoders.push_back(pHuffman);
183   return fHuffmanCoders.size()-1;
184 }
185
186 bool AliHLTDataDeflaterHuffman::AddTrainingValue( int memberId, AliHLTUInt64_t const & value )
187 {
188   /// add a training value for the specified parameter
189   if (memberId>=(int)fHuffmanCoders.size()) {
190     return false;
191   }
192   return fHuffmanCoders[memberId]->AddTrainingValue(value);
193 }
194
195 const TList* AliHLTDataDeflaterHuffman::GenerateHuffmanTree()
196 {
197   /// generate the huffman tree
198   for (unsigned i=0; i<fHuffmanCoders.size(); i++) {
199     if (!fHuffmanCoders[i]->GenerateHuffmanTree()) {
200       HLTError("failed to generate huffman tree for parameter %s", fHuffmanCoders[i]->GetName());
201     }
202   }
203   return fHuffmanCoderList;
204 }
205
206 void AliHLTDataDeflaterHuffman::Clear(Option_t * option)
207 {
208   // internal cleanup
209
210   AliHLTDataDeflater::Clear(option);
211 }
212
213 void AliHLTDataDeflaterHuffman::Print(Option_t *option) const
214 {
215   // print info
216   Print(cout, option);
217 }
218
219 void AliHLTDataDeflaterHuffman::Print(ostream& out, Option_t * /*option*/) const
220 {
221   // print to stream
222   out << "AliHLTDataDeflaterHuffman:" << endl;
223   for (vector<AliHLTHuffman*>::const_iterator it=fHuffmanCoders.begin();
224        it!=fHuffmanCoders.end(); it++) {
225     (*it)->Print("short"); cout << endl;
226   }
227   if (fHuffmanCoders.size()==0 && fHuffmanCoderList && fHuffmanCoderList->GetEntries()>0) {
228     TIter next(fHuffmanCoderList);
229     TObject* pObj=NULL;
230     while ((pObj=next())) {
231       pObj->Print("short"); cout << endl;
232     }
233   }
234 }
235
236 TObject *AliHLTDataDeflaterHuffman::FindObject(const char *name) const
237 {
238   /// find object: 'DeflaterConfiguration'
239   if (strcmp(name, "DeflaterConfiguration")==0) {
240     for (unsigned i=0; i<fHuffmanCoders.size(); i++) {
241       if (!fHuffmanCoders[i]->GenerateHuffmanTree()) {
242         HLTError("generation of huffman tree for parameter '%s' failed", fHuffmanCoders[i]->GetName());
243         return NULL;
244       }
245       if (!fHuffmanCoders[i]->CheckConsistency()) {
246         HLTError("consistency check of huffman tree for parameter '%s' failed", fHuffmanCoders[i]->GetName());
247       }
248     }
249     
250     return fHuffmanCoderList;
251   }
252
253   return NULL;
254 }
255
256 void AliHLTDataDeflaterHuffman::SaveAs(const char *filename, Option_t *option) const
257 {
258   /// save data according to option
259   TString remainingOptions;
260   bool bWriteHuffmanConf=false; // write the huffman configuration
261   TString strOption(option);
262   std::auto_ptr<TObjArray> tokens(strOption.Tokenize(" "));
263   if (tokens.get()) {
264     for (int i=0; i<tokens->GetEntriesFast(); i++) {
265       if (!tokens->At(i)) continue;
266       const char* key="";
267       TString arg=tokens->At(i)->GetName();
268
269       key="huffmanconf";
270       if (arg.BeginsWith(key)) {
271         bWriteHuffmanConf=true;
272         continue;
273       }
274
275       if (!remainingOptions.IsNull()) remainingOptions+=" ";
276       remainingOptions+=arg;
277     }
278   }
279
280   if (bWriteHuffmanConf) {
281     std::auto_ptr<TFile> output(TFile::Open(filename, "RECREATE"));
282     if (!output.get() || output->IsZombie()) {
283       HLTError("can not open file %s from writing", filename);
284       return;
285     }
286
287     if (!fHuffmanCoderList || fHuffmanCoderList->GetEntries()==0) {
288       HLTError("no huffman instances available for writing");
289       return;
290     }
291
292     for (unsigned i=0; i<fHuffmanCoders.size(); i++) {
293       if (!fHuffmanCoders[i]->GenerateHuffmanTree()) {
294         HLTError("generation of huffman tree for parameter '%s' failed", fHuffmanCoders[i]->GetName());
295       }
296     }
297
298     output->cd();
299     fHuffmanCoderList->Write("DeflaterConfiguration", TObject::kSingleKey);
300     output->Close();
301     return;
302   }
303
304   return AliHLTDataDeflater::SaveAs(filename, remainingOptions);
305 }
306
307 ostream& operator<<(ostream &out, const AliHLTDataDeflaterHuffman& me)
308 {
309   me.Print(out);
310   return out;
311 }
312