// Copyright CERN and copyright holders of ALICE O2. This software is // distributed under the terms of the GNU General Public License v3 (GPL // Version 3), copied verbatim in the file "COPYING". // // See http://alice-o2.web.cern.ch/license for full licensing information. // // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. /// @file Decoder.h /// @author Michael Lettrich /// @since 2020-04-06 /// @brief Decoder - decode a rANS encoded state back into source symbols #ifndef RANS_DECODER_H #define RANS_DECODER_H #include "internal/Decoder.h" #include #include #include #include #include #include "FrequencyTable.h" #include "internal/DecoderSymbol.h" #include "internal/ReverseSymbolLookupTable.h" #include "internal/SymbolTable.h" #include "internal/Decoder.h" #include "internal/SymbolStatistics.h" namespace o2 { namespace rans { template class Decoder { protected: using decoderSymbolTable_t = internal::SymbolTable; using reverseSymbolLookupTable_t = internal::ReverseSymbolLookupTable; using ransDecoder = internal::Decoder; public: Decoder(const Decoder& d); Decoder(Decoder&& d) = default; Decoder& operator=(const Decoder& d); Decoder& operator=(Decoder&& d) = default; ~Decoder() = default; Decoder(const FrequencyTable& stats, size_t probabilityBits); template void process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength) const; size_t getAlphabetRangeBits() const { return mSymbolTable->getAlphabetRangeBits(); } int getMinSymbol() const { return mSymbolTable->getMinSymbol(); } int getMaxSymbol() const { return mSymbolTable->getMaxSymbol(); } using coder_t = coder_T; using stream_t = stream_T; using source_t = source_T; protected: std::unique_ptr mSymbolTable; std::unique_ptr mReverseLUT; size_t mProbabilityBits; }; template Decoder::Decoder(const Decoder& d) : mSymbolTable(nullptr), mReverseLUT(nullptr), mProbabilityBits(d.mProbabilityBits) { mSymbolTable = std::make_unique(*d.mSymbolTable); mReverseLUT = std::make_unique(*d.mReverseLUT); } template Decoder& Decoder::operator=(const Decoder& d) { mSymbolTable = std::make_unique(*d.mSymbolTable); mReverseLUT = std::make_unique(*d.mReverseLUT); mProbabilityBits = d.mProbabilityBits; return *this; } template Decoder::Decoder(const FrequencyTable& frequencies, size_t probabilityBits) : mSymbolTable(nullptr), mReverseLUT(nullptr), mProbabilityBits(probabilityBits) { using namespace internal; SymbolStatistics stats(frequencies, mProbabilityBits); mProbabilityBits = stats.getSymbolTablePrecision(); RANSTimer t; t.start(); mSymbolTable = std::make_unique(stats); t.stop(); LOG(debug1) << "Decoder SymbolTable inclusive time (ms): " << t.getDurationMS(); t.start(); mReverseLUT = std::make_unique(mProbabilityBits, stats); t.stop(); LOG(debug1) << "ReverseSymbolLookupTable inclusive time (ms): " << t.getDurationMS(); }; template template void Decoder::process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength) const { using namespace internal; LOG(trace) << "start decoding"; RANSTimer t; t.start(); static_assert(std::is_same::value_type, source_T>::value); static_assert(std::is_same::value_type, stream_T>::value); if (messageLength == 0) { LOG(warning) << "Empty message passed to decoder, skipping decode process"; return; } stream_IT inputIter = inputEnd; source_IT it = outputBegin; // make Iter point to the last last element --inputIter; ransDecoder rans0, rans1; inputIter = rans0.init(inputIter); inputIter = rans1.init(inputIter); for (size_t i = 0; i < (messageLength & ~1); i += 2) { const int64_t s0 = (*mReverseLUT)[rans0.get(mProbabilityBits)]; const int64_t s1 = (*mReverseLUT)[rans1.get(mProbabilityBits)]; *it++ = s0; *it++ = s1; inputIter = rans0.advanceSymbol(inputIter, (*mSymbolTable)[s0], mProbabilityBits); inputIter = rans1.advanceSymbol(inputIter, (*mSymbolTable)[s1], mProbabilityBits); } // last byte, if message length was odd if (messageLength & 1) { const int64_t s0 = (*mReverseLUT)[rans0.get(mProbabilityBits)]; *it = s0; inputIter = rans0.advanceSymbol(inputIter, (*mSymbolTable)[s0], mProbabilityBits); } t.stop(); LOG(debug1) << "Decoder::" << __func__ << " { DecodedSymbols: " << messageLength << "," << "processedBytes: " << messageLength * sizeof(source_T) << "," << " inclusiveTimeMS: " << t.getDurationMS() << "," << " BandwidthMiBPS: " << std::fixed << std::setprecision(2) << (messageLength * sizeof(source_T) * 1.0) / (t.getDurationS() * 1.0 * (1 << 20)) << "}"; LOG(trace) << "done decoding"; } } // namespace rans } // namespace o2 #endif /* RANS_DECODER_H */