]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/BASE/AliHLTHuffman.cxx
dedx method is float but variable declared int, corrected
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTHuffman.cxx
CommitLineData
6a1b3945 1// $Id$
2//**************************************************************************
3//* This file is property of and copyright by the ALICE HLT Project *
4//* ALICE Experiment at CERN, All rights reserved. *
5//* *
6//* Primary Authors: Thorsten Kollegger <kollegge@ikf.uni-frankfurt.de> *
7//* for The ALICE HLT Project. *
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 AliHLTHuffman.cxx
19/// @author Thorsten Kollegger, Matthias Richter
20/// @date 2011-08-14
21/// @brief Huffman code generator/encoder/decoder
22
23#include "AliHLTHuffman.h"
24
25#include <iostream>
26#include <set>
27#include <bitset>
28#include <algorithm>
29
30AliHLTHuffmanNode::AliHLTHuffmanNode()
31 : TObject()
32 , fValue(-1)
33 , fWeight(0.)
34{
35 // nop
36}
37
38AliHLTHuffmanNode::AliHLTHuffmanNode(const AliHLTHuffmanNode& other)
39 : TObject()
40 , fValue(other.GetValue())
41 , fWeight(other.GetWeight())
42{
43}
44
45AliHLTHuffmanNode& AliHLTHuffmanNode::operator =(const AliHLTHuffmanNode& other) {
46 /// assignment operator
47 this->fValue = other.fValue;
48 this->fWeight = other.fWeight;
49 return *this;
50}
51
52AliHLTHuffmanNode::~AliHLTHuffmanNode() {
53}
54
55void AliHLTHuffmanNode::AssignCode() {
56 /// assign code to this node loop to right and left nodes
57 if (GetLeftChild()) {
58 // shift current bit pattern to left and add one
59 std::bitset < 64 > v = (this->GetBinaryCode() << 1);
60 v.set(0);
61 GetLeftChild()->SetBinaryCode(this->GetBinaryCodeLength() + 1, v);
62 GetLeftChild()->AssignCode();
63 }
64 if (GetRightChild()) {
65 std::bitset < 64 > v = (this->GetBinaryCode() << 1);
66 v.reset(0);
67 GetRightChild()->SetBinaryCode(this->GetBinaryCodeLength() + 1, v);
68 GetRightChild()->AssignCode();
69 }
70}
71
72void AliHLTHuffmanNode::Print(Option_t* /*option*/) const {
73 /// print info
74 std::cout << "value=" << GetValue() << ", weight=" << GetWeight() << ", length="
75 << GetBinaryCodeLength() << ", code=" << GetBinaryCode().to_string()
76 << std::endl;
77 if (GetLeftChild()) {
78 GetLeftChild()->Print();
79 }
80 if (GetRightChild()) {
81 GetRightChild()->Print();
82 }
83}
84
85ClassImp(AliHLTHuffmanNode)
86
87///////////////////////////////////////////////////////////////////////////////////////////////
88
89AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode()
90 : AliHLTHuffmanNode()
91 , fBinaryCodeLength(0)
92 , fBinaryCode(0)
93 , fLeft(NULL)
94 , fRight(NULL)
95{
96 // nop
97}
98
99AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode(const AliHLTHuffmanTreeNode& other)
100 : AliHLTHuffmanNode()
101 , fBinaryCodeLength(other.fBinaryCodeLength)
102 , fBinaryCode(other.fBinaryCode)
103 , fLeft(other.GetLeftChild())
104 , fRight(other.GetRightChild())
105{
106
107}
108
109AliHLTHuffmanTreeNode& AliHLTHuffmanTreeNode::operator =(const AliHLTHuffmanTreeNode& other)
110{
111 /// assignment operator
112 if (&other==this) return *this;
113 this->fBinaryCodeLength = other.GetBinaryCodeLength();
114 this->fBinaryCode = other.GetBinaryCode();
115 this->fLeft = other.GetLeftChild();
116 this->fRight = other.GetRightChild();
117 AliHLTHuffmanNode::operator=(other);
118 return *this;
119}
120
121AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode(AliHLTHuffmanNode* l, AliHLTHuffmanNode* r)
122 : AliHLTHuffmanNode()
123 , fBinaryCodeLength(0)
124 , fBinaryCode(0)
125 , fLeft(l)
126 , fRight(r) {
127 if (l && r) {
128 SetWeight(l->GetWeight() + r->GetWeight());
129 } else if (l && !r) {
130 SetWeight(l->GetWeight());
131 } else if (!l && r) {
132 SetWeight(r->GetWeight());
133 }
134}
135
136AliHLTHuffmanTreeNode::~AliHLTHuffmanTreeNode()
137{
138 // nop
139}
140
141ClassImp(AliHLTHuffmanTreeNode)
142
143///////////////////////////////////////////////////////////////////////////////////////////////
144
145AliHLTHuffmanLeaveNode::AliHLTHuffmanLeaveNode()
146 : AliHLTHuffmanNode()
147 , fBinaryCodeLength(0)
148 , fBinaryCode(0)
149 , fLeft(NULL)
150 , fRight(NULL)
151{
152 // nop
153}
154
155AliHLTHuffmanLeaveNode::AliHLTHuffmanLeaveNode(const AliHLTHuffmanLeaveNode& other)
156 : AliHLTHuffmanNode()
157 , fBinaryCodeLength(other.fBinaryCodeLength)
158 , fBinaryCode(other.fBinaryCode)
159 , fLeft(other.GetLeftChild())
160 , fRight(other.GetRightChild())
161{
162
163}
164
165AliHLTHuffmanLeaveNode& AliHLTHuffmanLeaveNode::operator =(const AliHLTHuffmanLeaveNode& other)
166{
167 /// assignment operator
168 if (&other==this) return *this;
169 this->fBinaryCodeLength = other.GetBinaryCodeLength();
170 this->fBinaryCode = other.GetBinaryCode();
171 this->fLeft = other.GetLeftChild();
172 this->fRight = other.GetRightChild();
173 AliHLTHuffmanNode::operator=(other);
174 return *this;
175}
176
177AliHLTHuffmanLeaveNode::~AliHLTHuffmanLeaveNode()
178{
179 // nop
180}
181
182ClassImp(AliHLTHuffmanLeaveNode)
183
184///////////////////////////////////////////////////////////////////////////////////////////////
185
186AliHLTHuffman::AliHLTHuffman()
187 : TNamed()
188 , fMaxBits(0)
189 , fMaxValue(0)
190 , fNodes(0)
191 , fHuffTopNode(NULL)
192{
193 /// nop
194}
195
196AliHLTHuffman::AliHLTHuffman(const AliHLTHuffman& other)
197 : TNamed()
198 , AliHLTLogging()
199 , fMaxBits(other.fMaxBits)
200 , fMaxValue(other.fMaxValue)
201 , fNodes(other.fNodes)
202 , fHuffTopNode(NULL) {
203 /// nop
204}
205
206AliHLTHuffman::AliHLTHuffman(const char* name, UInt_t maxBits)
207 : TNamed(name, name)
208 , fMaxBits(maxBits)
209 , fMaxValue((((AliHLTUInt64_t) 1) << maxBits) - 1)
210 , fNodes((((AliHLTUInt64_t) 1) << maxBits))
211 , fHuffTopNode(NULL)
212 {
213 /// standard constructor
214 for (AliHLTUInt64_t i = 0; i <= fMaxValue; i++) {
215 fNodes[i].SetValue(i);
216 }
217}
218
219AliHLTHuffman::~AliHLTHuffman() {
220 /// destructor, nop
221}
222
223const std::bitset<64>& AliHLTHuffman::Encode(const AliHLTUInt64_t v, AliHLTUInt64_t& codeLength) const {
224 /// encode a value
225 codeLength = 0;
226 if (v <= fMaxValue) {
227 // valid symbol/value
228 if (fHuffTopNode) {
229 // huffman code has been generated
230 codeLength = fNodes[v].GetBinaryCodeLength();
231 return fNodes[v].GetBinaryCode();
232 } else {
233 HLTError("encoder '%s' does not seem to be initialized", GetName());
234 }
235 } else {
236 HLTError("encoder %s: value %llu exceeds range of %d bits", GetName(), v, GetMaxBits());
237 }
238
239 static const std::bitset<64> dummy;
240 return dummy;
241}
242
243Bool_t AliHLTHuffman::Decode(std::bitset<64> bits, AliHLTUInt64_t& value) const {
244 // TODO: check decoding logic, righ now it is just as written
245 AliHLTHuffmanNode* currNode = fHuffTopNode;
cac77957 246 if (!currNode) return kFALSE;
6a1b3945 247 if (currNode->GetValue() >= 0) {
248 // handle case with just one node - also quite unlikely
249 value = currNode->GetValue();
250 return kTRUE;
251 }
252 while (currNode) {
253 if (bits[0] && currNode->GetLeftChild()) {
254 // follow left branch
255 currNode = currNode->GetLeftChild();
256 bits >>= 1;
257 if (currNode->GetValue() >= 0) {
258 value = currNode->GetValue();
259 return kTRUE;
260 }
261 }
262 if (!bits[0] && currNode->GetRightChild()) {
263 currNode = currNode->GetRightChild();
264 bits >>= 1;
265 if (currNode->GetValue() >= 0) {
266 value = currNode->GetValue();
267 return kTRUE;
268 }
269 }
270 }
271 value = ((AliHLTUInt64_t)1) << 63;
272 return kFALSE;
273}
274
275Bool_t AliHLTHuffman::AddTrainingValue(const AliHLTUInt64_t value,
84a44d88 276 const Float_t weight) {
6a1b3945 277 if (value > fMaxValue) {
278 /* TODO: ERROR message */
279 return kFALSE;
280 }
281 fNodes[value].AddWeight(weight);
282 return kTRUE;
283}
284
285Bool_t AliHLTHuffman::GenerateHuffmanTree() {
286 // insert pointer to nodes into ordered structure to build tree
287 std::multiset<AliHLTHuffmanNode*, AliHLTHuffmanNode::less> nodeCollection;
288 // std::copy(fNodes.begin(), fNodes.end(),
289 // std::inserter(freq_coll, freq_coll.begin()));
290 for (std::vector<AliHLTHuffmanLeaveNode>::iterator i = fNodes.begin(); i
291 != fNodes.end(); ++i) {
292 nodeCollection.insert(&(*i));
293 }
294 while (nodeCollection.size() > 1) {
295 // insert new node into structure, combining the two with lowest probability
296 nodeCollection.insert(
297 new AliHLTHuffmanTreeNode(*nodeCollection.begin(),
298 *++nodeCollection.begin()));
299 nodeCollection.erase(nodeCollection.begin());
300 nodeCollection.erase(nodeCollection.begin());
301 }
302 //assign value
303 fHuffTopNode = *nodeCollection.begin();
304 fHuffTopNode->AssignCode();
305 return kTRUE;
306}
307
308void AliHLTHuffman::Print(Option_t* option) const {
309 std::cout << GetName() << endl;
310 bool bPrintShort=strcmp(option, "short")==0;
311 if (fHuffTopNode && !bPrintShort) {
312 std::cout << "Huffman tree:" << endl;
313 fHuffTopNode->Print();
314 }
315 Double_t uncompressedSize = 0;
316 Double_t compressedSize = 0;
317 Double_t totalWeight = 0;
318 if (!bPrintShort)
319 std::cout << std::endl << "Huffman codes:" << std::endl;
320 for (AliHLTUInt64_t i = 0; i <= fMaxValue; i++) {
321 if (!bPrintShort) fNodes[i].Print();
322 totalWeight += fNodes[i].GetWeight();
323 uncompressedSize += fNodes[i].GetWeight() * fMaxBits;
324 compressedSize += fNodes[i].GetWeight()
325 * fNodes[i].GetBinaryCodeLength();
326 }
327 if (uncompressedSize > 0) {
328 std::cout << "compression ratio: " << compressedSize
329 / uncompressedSize << std::endl;
330 std::cout << "<bits> uncompressed: " << uncompressedSize / totalWeight
331 << std::endl;
332 std::cout << "<bits> compressed: " << compressedSize / totalWeight
333 << std::endl;
334 }
335}
336
337AliHLTHuffman& AliHLTHuffman::operator =(const AliHLTHuffman& other) {
338 fMaxValue = other.fMaxValue;
339 fNodes = other.fNodes;
340 fHuffTopNode = NULL;
341 return *this;
342}
343
344ClassImp(AliHLTHuffman)
345