int HuffmanCodec::decode( int* raw, int rawCapacity, BitDecoder* source ) { /** read header */ int rawFill = source ->readUIntVlc(); int rawMin = source->readIntVlc(); int rawMax = source->readIntVlc(); int encodingFlag = source->readBit(); if (rawFill > rawCapacity) FTL_THROW(StreamSemanticException, "Decoding buffer of insufficient size provided."); /** optional fallback to raw data transmission */ if (encodingFlag == 0) { const int bits = ilog2(rawMax - rawMin + 1); for (int i = 0; i < rawFill; ++i) raw[i] = int(source->readUIntVlc(bits)) + rawMin; return rawFill; } /** read frequency table */ reset(); int diversity = source ->readUIntVlc(); for (int i = 0; i < diversity; ++i) { int value = source->readUIntVlc(); int count = source->readUIntVlc(); addSymbol(value, count); } /** generate code table */ generateCodeTable(); /** decode symbols */ for (int i = 0; i < rawFill; ++i) { SymbolNode* sym = codeTableRoot_; while (sym->leftChild) sym = (source->readBit()) ? sym->rightChild : sym->leftChild; raw[i] = sym->value + rawMin; } return rawFill; }
void generateCode (void) { FILE* spec, *opcodes, *code, *table; /* ----- Read the specification ----- */ printf("Reading specification..."); spec = openOrDie(OPCODES_SPEC, "rb"); if (!readSpec(spec)) fatal("Error reading the specification"); fclose(spec); printf("done\n"); opcodes = openOrDie(OPCODES_LIST, "rb"); code = openOrDie(OPCODES_IMPL, "wb"); generateCodeTable(opcodes, code); fclose(opcodes); fclose(code); }
void HuffmanCodec::encode(BitEncoder* sink, int* raw, int rawFill, bool* userFallback) { /** determine dynamic range (min, max) */ int rawMin = raw[0]; int rawMax = raw[0]; { for (int i = 1; i < rawFill; ++i) { int x = raw[i]; if (x < rawMin) rawMin = x; else if (x > rawMax) rawMax = x; } } /** optional fallback to raw data transmission */ if (rawMax - rawMin + 1 > rawDynamicRange_) { #ifdef FTL_HUFFMANCODEC_PROFILING print( "Fallback to unencoded transmission, because out of dynamic range.\n" " (rawMax - rawMin + 1, rawDynamicRange_) = (%%, %%)\n", (rawMax - rawMin + 1), rawDynamicRange_ ); #endif // FTL_HUFFMANCODEC_PROFILING if (!userFallback) writeRawFrame(sink, raw, rawFill, rawMin, rawMax); else *userFallback = true; return; } /** determine symbol frequencies */ reset(); for (int i = 0; (i < rawFill) && (codeTableFill_ < rawDiversity_); ++i) { int x = raw[i] - rawMin; if (!codeMap_[x].symbol) addSymbol(x, 0); ++codeMap_[x].symbol->count; } /** optional fallback to raw data transmission */ if (codeTableFill_ == rawDiversity_) { if (!userFallback) writeRawFrame(sink, raw, rawFill, rawMin, rawMax); else *userFallback = true; return; } /** generate code table */ int diversity = codeTableFill_; generateCodeTable(); #ifdef FTL_HUFFMANCODEC_DEBUG_STATISTICS for (int i = 0; i < diversity; ++i) { FTL_DEBUG << i << ": H(" << codeTable_[i].value << ") = " << codeTable_[i].count << endl; } #endif /** determine output size */ int tableSize = 0; int outSize = 1; // encoding flag outSize += BitEncoder::bitsPerUIntVlc(rawFill); outSize += BitEncoder::bitsPerUIntVlc(rawMin); tableSize += BitEncoder::bitsPerUIntVlc(diversity); for (int i = 0; i < diversity; ++i) { tableSize += BitEncoder::bitsPerUIntVlc(codeTable_[i].value); tableSize += BitEncoder::bitsPerUIntVlc(codeTable_[i].count); SymbolNode* sym = codeTable_ + i; int len = 0; while ((sym = sym->parent) != 0) ++len; outSize += len * codeTable_[i].count; } outSize += tableSize; int outSizeBytes = outSize / 8 + (outSize % 8 != 0); #ifdef FTL_HUFFMANCODEC_PROFILING print( "diversity, outSize, table weight = %%, %%, %%\n", diversity, outSize/8, double(tableSize) / outSize ); #endif // FTL_HUFFMANCODEC_PROFILING /** optional fallback to raw data transmission */ if (outSizeBytes > encodedCapacity(rawFill, rawMax-rawMin+1)) { #ifdef FTL_HUFFMANCODEC_PROFILING print("fallback to unencoded transmission\n"); #endif // FTL_HUFFMANCODEC_PROFILING if (!userFallback) writeRawFrame(sink, raw, rawFill, rawMin, rawMax); else *userFallback = true; return; } if (userFallback) *userFallback = false; /** write header */ sink->writeUIntVlc(rawFill); sink->writeIntVlc(rawMin); sink->writeIntVlc(rawMax); sink->writeBit(1); // encoding flag /** write frequency table */ sink->writeUIntVlc(diversity); for (int i = 0; i < diversity; ++i) { sink->writeUIntVlc(codeTable_[i].value); sink->writeUIntVlc(codeTable_[i].count); } /** encode symbols */ for (int i = 0; i < rawFill; ++i) { int x = raw[i] - rawMin; SymbolNode* sym = codeMap_[x].symbol; bitStack_.clear(); while (sym->parent) { SymbolNode* parent = sym->parent; bitStack_.push(parent->rightChild == sym); sym = parent; } while (bitStack_.fill() > 0) sink->writeBit(bitStack_.pop()); } }