3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Thorsten Kollegger <kollegge@ikf.uni-frankfurt.de> *
8 //* for The ALICE HLT Project. *
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 //**************************************************************************
19 /// @file AliHLTDataDeflaterHuffman.cxx
20 /// @author Thorsten Kollegger, Matthias Richter
22 /// @brief Deflater implementation using huffman code
24 #include "AliHLTDataDeflaterHuffman.h"
25 #include "AliHLTHuffman.h"
26 #include "TObjArray.h"
34 /** ROOT macro for the implementation of ROOT specific class methods */
35 ClassImp(AliHLTDataDeflaterHuffman)
37 AliHLTDataDeflaterHuffman::AliHLTDataDeflaterHuffman(bool bTrainingMode)
38 : AliHLTDataDeflater()
41 , fHuffmanCoderList(NULL)
42 , fTrainingMode(bTrainingMode)
44 // see header file for class documentation
46 // refer to README to build package
48 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
50 HLTInfo("using DataDeflaterHuffman in training mode");
54 AliHLTDataDeflaterHuffman::~AliHLTDataDeflaterHuffman()
57 if (fHuffmanCoderList) delete fHuffmanCoderList;
58 fHuffmanCoderList=NULL;
63 int AliHLTDataDeflaterHuffman::AddParameterDefinition(const char* name, unsigned bitLength, unsigned refLength)
65 /// search a parameter definition in the decoder configuration, and set the index
66 /// array, return reference id
68 return AddTrainingParameter(name, bitLength);
70 if (!name) return -EINVAL;
71 if (!fHuffmanCoderList) return -ENODEV;
72 TObject* pObj=fHuffmanCoderList->FindObject(name);
74 HLTError("can not find decoder of id '%s'", name);
77 AliHLTHuffman* pHuffman=dynamic_cast<AliHLTHuffman*>(pObj);
79 HLTError("object %s has wrong type, expected AliHLTHuffman", name);
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);
87 fReferenceLength.push_back(refLength);
88 fHuffmanCoders.push_back(pHuffman);
90 int memberId=fHuffmanCoders.size()-1;
92 AddHistogram(memberId, name, bitLength);
98 int AliHLTDataDeflaterHuffman::InitDecoders(TList* decoderlist)
100 /// init list of decoders
101 /// expects to be an external pointer, valid throughout the livetime of
103 if (!decoderlist) return -EINVAL;
104 if (!fHuffmanCoderList) {
105 fHuffmanCoderList=new TList;
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");
111 if (!fHuffmanCoderList) return -ENOMEM;
112 fHuffmanCoderList->SetOwner(kFALSE);
113 TIter next(decoderlist);
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());
121 fHuffmanCoderList->Add(pObj);
124 return fHuffmanCoderList->GetEntries();
127 bool AliHLTDataDeflaterHuffman::OutputParameterBits( int memberId, AliHLTUInt64_t const & value )
129 // write huffman encoded bit pattern of a member to the current byte and position
130 if (IsTrainingMode())
131 return AddTrainingValue(memberId, value);
133 if (memberId>=(int)fHuffmanCoders.size()) {
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()) {
142 unsigned parameterLength=fHuffmanCoders[memberId]->GetMaxBits();
143 if (memberId<(int)fReferenceLength.size() && fReferenceLength[memberId]>0)
144 parameterLength=fReferenceLength[memberId];
145 if (parameterLength>0) {
147 weight/=parameterLength;
149 FillStatistics(memberId, value, length, weight);
153 return OutputBits(v, length);
159 int AliHLTDataDeflaterHuffman::AddTrainingParameter(const char* name, unsigned bitLength)
161 /// add a parameter definition for huffman training
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");
175 fHuffmanCoderList->SetOwner();
178 AliHLTHuffman* pHuffman=new AliHLTHuffman(name, bitLength);
179 if (!pHuffman) return -ENOMEM;
180 fHuffmanCoderList->Add(pHuffman);
182 fHuffmanCoders.push_back(pHuffman);
183 return fHuffmanCoders.size()-1;
186 bool AliHLTDataDeflaterHuffman::AddTrainingValue( int memberId, AliHLTUInt64_t const & value )
188 /// add a training value for the specified parameter
189 if (memberId>=(int)fHuffmanCoders.size()) {
192 return fHuffmanCoders[memberId]->AddTrainingValue(value);
195 const TList* AliHLTDataDeflaterHuffman::GenerateHuffmanTree()
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());
203 return fHuffmanCoderList;
206 void AliHLTDataDeflaterHuffman::Clear(Option_t * option)
210 AliHLTDataDeflater::Clear(option);
213 void AliHLTDataDeflaterHuffman::Print(Option_t *option) const
219 void AliHLTDataDeflaterHuffman::Print(ostream& out, Option_t * /*option*/) const
222 out << "AliHLTDataDeflaterHuffman:" << endl;
223 for (vector<AliHLTHuffman*>::const_iterator it=fHuffmanCoders.begin();
224 it!=fHuffmanCoders.end(); it++) {
225 (*it)->Print("short"); cout << endl;
227 if (fHuffmanCoders.size()==0 && fHuffmanCoderList && fHuffmanCoderList->GetEntries()>0) {
228 TIter next(fHuffmanCoderList);
230 while ((pObj=next())) {
231 pObj->Print("short"); cout << endl;
236 TObject *AliHLTDataDeflaterHuffman::FindObject(const char *name) const
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());
245 if (!fHuffmanCoders[i]->CheckConsistency()) {
246 HLTError("consistency check of huffman tree for parameter '%s' failed", fHuffmanCoders[i]->GetName());
250 return fHuffmanCoderList;
256 void AliHLTDataDeflaterHuffman::SaveAs(const char *filename, Option_t *option) const
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(" "));
264 for (int i=0; i<tokens->GetEntriesFast(); i++) {
265 if (!tokens->At(i)) continue;
267 TString arg=tokens->At(i)->GetName();
270 if (arg.BeginsWith(key)) {
271 bWriteHuffmanConf=true;
275 if (!remainingOptions.IsNull()) remainingOptions+=" ";
276 remainingOptions+=arg;
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);
287 if (!fHuffmanCoderList || fHuffmanCoderList->GetEntries()==0) {
288 HLTError("no huffman instances available for writing");
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());
299 fHuffmanCoderList->Write("DeflaterConfiguration", TObject::kSingleKey);
304 return AliHLTDataDeflater::SaveAs(filename, remainingOptions);
307 ostream& operator<<(ostream &out, const AliHLTDataDeflaterHuffman& me)