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