, fHuffmanCoderList(NULL)
, fCurrentParameter(-1)
, fLegacyMode(-1)
+ , fInput(0)
+ , fInputLength(0)
{
// see header file for class documentation
// or
TIter next(decoderlist);
TObject* pObj=NULL;
while ((pObj=next())!=NULL) {
- if (dynamic_cast<AliHLTHuffman*>(pObj)==NULL) continue;
+ AliHLTHuffman* coder=NULL;
+ if ((coder=dynamic_cast<AliHLTHuffman*>(pObj))==NULL) continue;
if (fHuffmanCoderList->FindObject(pObj->GetName())) {
HLTError("duplicate entry of name '%s'", pObj->GetName());
return -EEXIST;
}
fHuffmanCoderList->Add(pObj);
+ coder->InitMaxCodeLength();
}
return fHuffmanCoderList->GetEntries();
/// list, than it starts at the first parameter again
value=0;
length=0;
- AliHLTUInt64_t input=0;
- AliHLTUInt32_t inputLength=64;
- if (GetRemainingBitDataSizeBytes()<=sizeof(AliHLTUInt64_t)) {
- inputLength=8*GetRemainingBitDataSizeBytes();
- inputLength-=(7-GetCurrentBitInputPosition());
- }
- if (!InputBits(input, inputLength)) return false;
if (fLegacyMode!=0) {
if ((++fCurrentParameter)>=(int)fHuffmanCoders.size()) fCurrentParameter=0;
fLegacyMode=1;
}
if (fHuffmanCoders.size()==0 || fCurrentParameter<0) return false;
- // the huffman code is decoded from bit 0 corresponding to the top node and then to
- // the left. The bitstream stores the reversed huffman code from MSB to LSB to ensure
- // a continous bit stream, that's why then input word needs to be reversed before
- // decoding.
- // TODO: introducing DecodeReverse into AliHLTHuffman can speed up the reading
- std::bitset<64> bits;
- for (unsigned bit=0; bit<inputLength; bit++) {bits[inputLength-1-bit]=input&0x1;input>>=1;}
+ if (fInputLength<fHuffmanCoders[fCurrentParameter]->GetMaxCodeLength() ||
+ fHuffmanCoders[fCurrentParameter]->GetMaxCodeLength()==0)
+ {
+ AliHLTUInt64_t input=0;
+ AliHLTUInt32_t inputLength=64-fInputLength;
+ if (GetRemainingBitDataSizeBytes()<=sizeof(AliHLTUInt64_t)) {
+ inputLength=8*GetRemainingBitDataSizeBytes();
+ inputLength-=(7-GetCurrentBitInputPosition());
+ }
+ if (64-fInputLength<inputLength) inputLength=64-fInputLength;
+ if (!InputBits(input, inputLength)) return false;
+ input<<=(64-inputLength);
+ input>>=fInputLength;
+ fInput|=input;
+ fInputLength+=inputLength;
+ }
AliHLTUInt32_t codeLength=0;
- if (!fHuffmanCoders[fCurrentParameter]->Decode(bits, value, length, codeLength)) return false;
- if (inputLength<codeLength) {
+ if (!fHuffmanCoders[fCurrentParameter]->DecodeUp(fInput, value, length, codeLength)) return false;
+ if (fInputLength<codeLength) {
HLTError("huffman decoder '%s' pretends to have %d bit(s) decoded, but only %d available",
- fHuffmanCoders[fCurrentParameter]->GetName(), codeLength, inputLength);
+ fHuffmanCoders[fCurrentParameter]->GetName(), codeLength, fInputLength);
return false;
}
- inputLength-=codeLength;
- RewindBitPosition(inputLength);
+ fInput<<=codeLength;
+ fInputLength-=codeLength;
return true;
}
+void AliHLTDataInflaterHuffman::Print(Option_t* option) const
+{
+ /// Print info
+ for (vector<AliHLTHuffman*>::const_iterator coder=fHuffmanCoders.begin();
+ coder!=fHuffmanCoders.end(); coder++) {
+ if (!*coder) continue;
+ (*coder)->Print(option);
+ }
+}
+
void AliHLTDataInflaterHuffman::Clear(Option_t * option)
{
/// clear the object
fCurrentParameter=-1;
+ fInput=0;
+ fInputLength=0;
if (strcmp(option, "all")==0) {
fHuffmanCoders.clear();
return fCurrentParameter;
}
+ /// Print info
+ void Print(Option_t* option = "") const;
/// clear the object and reset pointer references
virtual void Clear(Option_t * option ="");
int fCurrentParameter; //!
/// legacy mode to handle code not using NextParameter()
int fLegacyMode;
+ /// buffered input
+ AliHLTUInt64_t fInput; //!
+ /// valid MSBs in the buffered input
+ AliHLTUInt32_t fInputLength; //!
ClassDef(AliHLTDataInflaterHuffman, 0)
};
}
AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode(const AliHLTHuffmanTreeNode& other)
- : AliHLTHuffmanNode()
+ : AliHLTHuffmanNode(other)
, fBinaryCodeLength(other.fBinaryCodeLength)
, fBinaryCode(other.fBinaryCode)
, fLeft(other.GetLeftChild())
}
AliHLTHuffmanLeaveNode::AliHLTHuffmanLeaveNode(const AliHLTHuffmanLeaveNode& other)
- : AliHLTHuffmanNode()
+ : AliHLTHuffmanNode(other)
, fBinaryCodeLength(other.fBinaryCodeLength)
, fBinaryCode(other.fBinaryCode)
, fLeft(other.GetLeftChild())
, fNodes(0)
, fHuffTopNode(NULL)
, fReverseCode(true)
+ , fMaxCodeLength(0)
{
/// nop
}
, fNodes(other.fNodes)
, fHuffTopNode(NULL)
, fReverseCode(other.fReverseCode)
+ , fMaxCodeLength(other.fMaxCodeLength)
{
/// nop
}
, fNodes((((AliHLTUInt64_t) 1) << maxBits))
, fHuffTopNode(NULL)
, fReverseCode(true)
+ , fMaxCodeLength(0)
{
/// standard constructor
for (AliHLTUInt64_t i = 0; i <= fMaxValue; i++) {
return dummy;
}
-Bool_t AliHLTHuffman::Decode(std::bitset<64> bits, AliHLTUInt64_t& value,
+Bool_t AliHLTHuffman::DecodeDown(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
+ // huffman decoding
AliHLTHuffmanNode* currNode = fHuffTopNode;
if (!currNode) return kFALSE;
if (currNode->GetValue() >= 0) {
return kFALSE;
}
+Bool_t AliHLTHuffman::DecodeUp(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->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->GetValue() >= 0) {
+ value = currNode->GetValue();
+ length = fMaxBits;
+ codeLength = currNode->GetBinaryCodeLength();
+ 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) {
//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();
fMaxValue = other.fMaxValue;
fNodes = other.fNodes;
fHuffTopNode = NULL;
+ fMaxCodeLength = 0;
return *this;
}
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 (!DecodeUp(code, readback, readbacklen, readbackcodelen)) {
+ cout << "Decode failed" << endl;
+ return false;
+ }
+ } else {
+ if (!DecodeDown(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;
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;
+}
+
ClassImp(AliHLTHuffman)
AliHLTHuffman(const char* name, UInt_t maxBits);
~AliHLTHuffman();
+ UInt_t InitMaxCodeLength();
+
UInt_t GetMaxBits() const {return fMaxBits;}
UInt_t GetMaxValue() const {return fMaxValue;}
+ UInt_t GetMaxCodeLength() const {return fMaxCodeLength;}
/// Return huffman code for a value
const std::bitset<64>& Encode(const AliHLTUInt64_t v, AliHLTUInt64_t& codeLength) const;
- /// Return value for bit pattern
- Bool_t Decode(std::bitset<64> /*bits*/, AliHLTUInt64_t& /*value*/, AliHLTUInt32_t& length, AliHLTUInt32_t& codeLength) const;
+ /// Return value for bit pattern, LSB first
+ Bool_t DecodeDown(std::bitset<64> /*bits*/, AliHLTUInt64_t& /*value*/, AliHLTUInt32_t& length, AliHLTUInt32_t& codeLength) const;
+ /// Return value for bit pattern, MSB first
+ Bool_t DecodeUp(std::bitset<64> /*bits*/, AliHLTUInt64_t& /*value*/, AliHLTUInt32_t& length, AliHLTUInt32_t& codeLength) const;
+
/// Add a new training value (with optional weight) to the training sample
Bool_t AddTrainingValue(const AliHLTUInt64_t value,
const Float_t weight = 1.);
std::vector<AliHLTHuffmanLeaveNode> fNodes; // array of nodes
AliHLTHuffmanNode* fHuffTopNode; // top node
bool fReverseCode; // indicate the type of the binary code
+ UInt_t fMaxCodeLength; //! maximum code length
-ClassDef(AliHLTHuffman, 2)
+ClassDef(AliHLTHuffman, 3)
};
#endif