]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - HLT/BASE/AliHLTHuffman.cxx
Merge branch 'master' into flatdev
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTHuffman.cxx
index 1a9dc5a8486ba5646b8b411b2fe8a6c40d7cd660..af0d13eb8d1d35bda0b1fe04edf8b1a3cb9a3f41 100644 (file)
@@ -44,6 +44,7 @@ AliHLTHuffmanNode::AliHLTHuffmanNode(const AliHLTHuffmanNode& other)
 
 AliHLTHuffmanNode& AliHLTHuffmanNode::operator =(const AliHLTHuffmanNode& other) {
         /// assignment operator
+        if (this==&other) return *this;
        this->fValue = other.fValue;
        this->fWeight = other.fWeight;
        return *this;
@@ -119,7 +120,7 @@ AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode()
 }
 
 AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode(const AliHLTHuffmanTreeNode& other)
-       : AliHLTHuffmanNode()
+       : AliHLTHuffmanNode(other)
        , fBinaryCodeLength(other.fBinaryCodeLength)
        , fBinaryCode(other.fBinaryCode)
        , fLeft(other.GetLeftChild())
@@ -175,7 +176,7 @@ AliHLTHuffmanLeaveNode::AliHLTHuffmanLeaveNode()
 }
 
 AliHLTHuffmanLeaveNode::AliHLTHuffmanLeaveNode(const AliHLTHuffmanLeaveNode& other)
-       : AliHLTHuffmanNode()
+       : AliHLTHuffmanNode(other)
        , fBinaryCodeLength(other.fBinaryCodeLength)
        , fBinaryCode(other.fBinaryCode)
        , fLeft(other.GetLeftChild())
@@ -212,6 +213,9 @@ AliHLTHuffman::AliHLTHuffman()
        , fNodes(0)
        , fHuffTopNode(NULL)
        , fReverseCode(true)
+       , fMaxCodeLength(0)
+       , fDecodingNodes()
+       , fDecodingTopNode(NULL)
 {
         /// nop
 }
@@ -224,6 +228,9 @@ AliHLTHuffman::AliHLTHuffman(const AliHLTHuffman& other)
        , fNodes(other.fNodes)
        , fHuffTopNode(NULL)
        , fReverseCode(other.fReverseCode)
+       , fMaxCodeLength(other.fMaxCodeLength)
+       , fDecodingNodes()
+       , fDecodingTopNode(NULL)
 {
         /// nop
 }
@@ -235,6 +242,9 @@ AliHLTHuffman::AliHLTHuffman(const char* name, UInt_t maxBits)
        , fNodes((((AliHLTUInt64_t) 1) << maxBits))
        , fHuffTopNode(NULL)
        , fReverseCode(true)
+       , fMaxCodeLength(0)
+       , fDecodingNodes()
+       , fDecodingTopNode(NULL)
  {
         /// standard constructor
        for (AliHLTUInt64_t i = 0; i <= fMaxValue; i++) {
@@ -266,9 +276,10 @@ const std::bitset<64>& AliHLTHuffman::Encode(const AliHLTUInt64_t v, AliHLTUInt6
        return dummy;
 }
 
-Bool_t AliHLTHuffman::Decode(std::bitset<64> bits, AliHLTUInt64_t& value,
-                            AliHLTUInt32_t& length, AliHLTUInt32_t& codeLength) const {
-       // TODO: check decoding logic, righ now it is just as written
+Bool_t AliHLTHuffman::DecodeLSB(std::bitset<64> bits, AliHLTUInt64_t& value,
+                               AliHLTUInt32_t& length, AliHLTUInt32_t& codeLength) const
+{
+       // huffman decoding
        AliHLTHuffmanNode* currNode = fHuffTopNode;
        if (!currNode) return kFALSE;
        if (currNode->GetValue() >= 0) {
@@ -281,7 +292,7 @@ Bool_t AliHLTHuffman::Decode(std::bitset<64> bits, AliHLTUInt64_t& value,
                        // follow left branch
                        currNode = currNode->GetLeftChild();
                        bits >>= 1;
-                       if (currNode->GetValue() >= 0) {
+                       if (currNode && currNode->GetValue() >= 0) {
                                value = currNode->GetValue();
                                length = fMaxBits;
                                codeLength = currNode->GetBinaryCodeLength();
@@ -292,7 +303,7 @@ Bool_t AliHLTHuffman::Decode(std::bitset<64> bits, AliHLTUInt64_t& value,
                if (!bits[0] && currNode->GetRightChild()) {
                        currNode = currNode->GetRightChild();
                        bits >>= 1;
-                       if (currNode->GetValue() >= 0) {
+                       if (currNode && currNode->GetValue() >= 0) {
                                value = currNode->GetValue();
                                length = fMaxBits;
                                codeLength = currNode->GetBinaryCodeLength();
@@ -306,6 +317,89 @@ Bool_t AliHLTHuffman::Decode(std::bitset<64> bits, AliHLTUInt64_t& value,
        return kFALSE;
 }
 
+Bool_t AliHLTHuffman::DecodeMSB(std::bitset<64> bits, AliHLTUInt64_t& value,
+                               AliHLTUInt32_t& length, AliHLTUInt32_t& codeLength) const
+{
+       // huffman decoding
+       AliHLTHuffmanNode* currNode = fHuffTopNode;
+       if (!currNode) return kFALSE;
+       if (currNode->GetValue() >= 0) {
+               // handle case with just one node - also quite unlikely
+               value = currNode->GetValue();
+               return kTRUE;
+       }
+       while (currNode) {
+               if (bits[63] && currNode->GetLeftChild()) {
+                       // follow left branch
+                       currNode = currNode->GetLeftChild();
+                       bits <<= 1;
+                       if (currNode && currNode->GetValue() >= 0) {
+                               value = currNode->GetValue();
+                               length = fMaxBits;
+                               codeLength = currNode->GetBinaryCodeLength();
+                               return kTRUE;
+                       }
+                       continue;
+               }
+               if (!bits[63] && currNode->GetRightChild()) {
+                       currNode = currNode->GetRightChild();
+                       bits <<= 1;
+                       if (currNode && currNode->GetValue() >= 0) {
+                               value = currNode->GetValue();
+                               length = fMaxBits;
+                               codeLength = currNode->GetBinaryCodeLength();
+                               return kTRUE;
+                       }
+                       continue;
+               }
+               break;
+       }
+       value = ((AliHLTUInt64_t)1) << 63;
+       return kFALSE;
+}
+
+Bool_t AliHLTHuffman::FastDecodeMSB(std::bitset<64> bits, AliHLTUInt64_t& value,
+                                   AliHLTUInt32_t& length, AliHLTUInt32_t& codeLength) const
+{
+       // huffman decoding using the binary node map
+        HLTFatal("this function needs to be tested and commisioned");
+       AliHuffmanDecodingNode* currNode = fDecodingTopNode;
+       if (!currNode) return kFALSE;
+       if (currNode->fValue >= 0) {
+               // handle case with just one node - also quite unlikely
+               value = currNode->fValue;
+               return kTRUE;
+       }
+       while (currNode) {
+               if (bits[63] && currNode->fLeft) {
+                       // follow left branch
+                       currNode = currNode->fLeft;
+                       bits <<= 1;
+                       if (currNode && currNode->fValue >= 0) {
+                               value = currNode->fValue;
+                               length = fMaxBits;
+                               codeLength = currNode->fBinaryCodeLength;
+                               return kTRUE;
+                       }
+                       continue;
+               }
+               if (!bits[63] && currNode->fRight) {
+                       currNode = currNode->fRight;
+                       bits <<= 1;
+                       if (currNode && currNode->fValue >= 0) {
+                               value = currNode->fValue;
+                               length = fMaxBits;
+                               codeLength = currNode->fBinaryCodeLength;
+                               return kTRUE;
+                       }
+                       continue;
+               }
+               break;
+       }
+       value = ((AliHLTUInt64_t)1) << 63;
+       return kFALSE;
+}
+
 Bool_t AliHLTHuffman::AddTrainingValue(const AliHLTUInt64_t value,
                const Float_t weight) {
        if (value > fMaxValue) {
@@ -336,12 +430,13 @@ Bool_t AliHLTHuffman::GenerateHuffmanTree() {
        //assign value
        fHuffTopNode = *nodeCollection.begin();
        fHuffTopNode->AssignCode(fReverseCode);
+       InitMaxCodeLength();
        return kTRUE;
 }
 
 void AliHLTHuffman::Print(Option_t* option) const {
         std::cout << GetName() << endl;
-        bool bPrintShort=strcmp(option, "short")==0;
+        bool bPrintShort=strcmp(option, "full")!=0;
        if (fHuffTopNode && !bPrintShort) {
                std::cout << "Huffman tree:" << endl;
                fHuffTopNode->Print();
@@ -369,9 +464,11 @@ void AliHLTHuffman::Print(Option_t* option) const {
 }
 
 AliHLTHuffman& AliHLTHuffman::operator =(const AliHLTHuffman& other) {
+        if (this==&other) return *this;
        fMaxValue = other.fMaxValue;
        fNodes = other.fNodes;
        fHuffTopNode = NULL;
+       fMaxCodeLength = 0;
        return *this;
 }
 
@@ -388,17 +485,17 @@ bool AliHLTHuffman::CheckConsistency() const
     AliHLTUInt32_t readbacklen=0;
     AliHLTUInt32_t readbackcodelen=0;
     if (fReverseCode) {
-      // reverse if needed
-      // Note: for optimized bit stream the huffman code is reversed, and
-      // that needs to be taken into account
-      std::bitset<64> rcode;
-      for (AliHLTUInt64_t i=0; i<codeLength; i++) {rcode<<=1; rcode[0]=code[i];}
-      code=rcode;
-    }
-    if (!Decode(code, readback, readbacklen, readbackcodelen)) {
+      code<<=64-codeLength;
+      if (!DecodeMSB(code, readback, readbacklen, readbackcodelen)) {
+       cout << "Decode failed" << endl;
+       return false;
+      }
+    } else {
+    if (!DecodeLSB(code, readback, readbacklen, readbackcodelen)) {
       cout << "Decode failed" << endl;
       return false;
     }
+    }
     if (v!=readback) {
       cout << "readback of value " << v << " code length " << codeLength << " failed: got " << readback << " code length " << readbackcodelen << endl;
       return false;
@@ -407,5 +504,76 @@ bool AliHLTHuffman::CheckConsistency() const
   return true;
 }
 
+UInt_t AliHLTHuffman::InitMaxCodeLength()
+{
+  // loop over leave nodes and set maximum code length
+  fMaxCodeLength=0;
+  for (std::vector<AliHLTHuffmanLeaveNode>::const_iterator node=fNodes.begin();
+       node!=fNodes.end(); node++) {
+    if (fMaxCodeLength<node->GetBinaryCodeLength())
+      fMaxCodeLength=node->GetBinaryCodeLength();
+  }
+  return fMaxCodeLength;
+}
+
+int AliHLTHuffman::EnableDecodingMap()
+{
+  // build decoder nodes from node tree
+  fDecodingTopNode=NULL;
+  fDecodingNodes.clear();
+  if (fNodes.size()==0) {
+    return 0;
+  }
+  fDecodingNodes.reserve(2*fNodes.size());
+  fDecodingTopNode=BuildDecodingNode(fHuffTopNode, fDecodingNodes);
+  if (!fDecodingTopNode) {
+    fDecodingNodes.clear();
+  } else {
+    HLTError("decoder nodes created sucessfully");
+  }
+  return 0;
+}
+
+AliHLTHuffman::AliHuffmanDecodingNode* AliHLTHuffman::BuildDecodingNode(AliHLTHuffmanNode* node, vector<AliHuffmanDecodingNode>& decodernodes) const
+{
+  // build and add decoder node structure corresponding to huffman node
+  if (!node) {
+    HLTError("invalid node pointer");
+    return NULL;
+  }
+  for (vector<AliHuffmanDecodingNode>::iterator i=decodernodes.begin();
+       i!=decodernodes.end(); i++) {
+    if (i->fParent==node) {
+      HLTError("node %p already existing in decoder nodes", node);
+      return NULL;
+    }
+  }
+
+  AliHuffmanDecodingNode* decodernode=NULL;
+  if (decodernodes.size()+1>decodernodes.capacity()) {
+    HLTError("initial size of array too small, can not add more nodes because pointers will become invalid when growing vector");
+  } else {
+    AliHuffmanDecodingNode dn;
+    dn.fParent=node;
+    dn.fValue=node->GetValue();
+    dn.fLeft=NULL;
+    dn.fRight=NULL;
+    dn.fBinaryCodeLength=0;
+    decodernodes.push_back(dn);
+    decodernode=&(decodernodes.back());
+  }
+
+  if (decodernode && decodernode->fValue<0) {
+    decodernode->fRight=BuildDecodingNode(node->GetRightChild(), decodernodes);
+    decodernode->fLeft=BuildDecodingNode(node->GetLeftChild(), decodernodes);
+    if (decodernode->fLeft==NULL || decodernode->fRight==0) {
+      HLTError("failed to build corresponding decoder node for node %p", node);
+      decodernode=NULL;
+    }
+  }
+
+  return decodernode;
+}
+
 ClassImp(AliHLTHuffman)