Skip to content

Commit

Permalink
[rANS] Cleanup Encoder/Decoder
Browse files Browse the repository at this point in the history
* Use `std::enable_if` type trait for compile-time type checks if
iterator holds correct value type
  • Loading branch information
MichaelLettrich authored and shahor02 committed Jan 15, 2021
1 parent 2751fcf commit 886a351
Show file tree
Hide file tree
Showing 9 changed files with 32 additions and 34 deletions.
7 changes: 3 additions & 4 deletions Utilities/rANS/include/rANS/Decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "internal/SymbolTable.h"
#include "internal/Decoder.h"
#include "internal/SymbolStatistics.h"
#include "internal/helper.h"

namespace o2
{
Expand All @@ -54,7 +55,7 @@ class Decoder
~Decoder() = default;
Decoder(const FrequencyTable& stats, size_t probabilityBits);

template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool> = true>
void process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength) const;

size_t getAlphabetRangeBits() const { return mSymbolTable->getAlphabetRangeBits(); }
Expand Down Expand Up @@ -107,15 +108,13 @@ Decoder<coder_T, stream_T, source_T>::Decoder(const FrequencyTable& frequencies,
};

template <typename coder_T, typename stream_T, typename source_T>
template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool>>
void Decoder<coder_T, stream_T, source_T>::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<typename std::iterator_traits<source_IT>::value_type, source_T>::value);
static_assert(std::is_same<typename std::iterator_traits<stream_IT>::value_type, stream_T>::value);

if (messageLength == 0) {
LOG(warning) << "Empty message passed to decoder, skipping decode process";
Expand Down
4 changes: 2 additions & 2 deletions Utilities/rANS/include/rANS/DedupDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ class DedupDecoder : public Decoder<coder_T, stream_T, source_T>
public:
using duplicatesMap_t = std::map<uint32_t, uint32_t>;

template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool> = true>
void process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength, duplicatesMap_t& duplicates) const;
};

template <typename coder_T, typename stream_T, typename source_T>
template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool>>
void DedupDecoder<coder_T, stream_T, source_T>::process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength, duplicatesMap_t& duplicates) const
{
using namespace internal;
Expand Down
4 changes: 2 additions & 2 deletions Utilities/rANS/include/rANS/DedupEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ class DedupEncoder : public Encoder<coder_T, stream_T, source_T>
public:
using duplicatesMap_t = std::map<uint32_t, uint32_t>;

template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool> = true>
const stream_IT process(const stream_IT outputBegin, const stream_IT outputEnd,
const source_IT inputBegin, source_IT inputEnd, duplicatesMap_t& duplicates) const;
};

template <typename coder_T, typename stream_T, typename source_T>
template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool>>
const stream_IT DedupEncoder<coder_T, stream_T, source_T>::process(const stream_IT outputBegin, const stream_IT outputEnd, const source_IT inputBegin, const source_IT inputEnd, duplicatesMap_t& duplicates) const
{
using namespace internal;
Expand Down
4 changes: 2 additions & 2 deletions Utilities/rANS/include/rANS/Encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class Encoder
Encoder(encoderSymbolTable_t&& e, size_t probabilityBits);
Encoder(const FrequencyTable& frequencies, size_t probabilityBits);

template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool> = true>
const stream_IT process(const stream_IT outputBegin, const stream_IT outputEnd,
const source_IT inputBegin, const source_IT inputEnd) const;

Expand Down Expand Up @@ -113,7 +113,7 @@ Encoder<coder_T, stream_T, source_T>::Encoder(const FrequencyTable& frequencies,
}

template <typename coder_T, typename stream_T, typename source_T>
template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool>>
const stream_IT Encoder<coder_T, stream_T, source_T>::Encoder::process(const stream_IT outputBegin, const stream_IT outputEnd, const source_IT inputBegin, const source_IT inputEnd) const
{
using namespace internal;
Expand Down
4 changes: 2 additions & 2 deletions Utilities/rANS/include/rANS/LiteralDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ class LiteralDecoder : public Decoder<coder_T, stream_T, source_T>
using Decoder<coder_T, stream_T, source_T>::Decoder;

public:
template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool> = true>
void process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength, std::vector<source_T>& literals) const;
};

template <typename coder_T, typename stream_T, typename source_T>
template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool>>
void LiteralDecoder<coder_T, stream_T, source_T>::process(const source_IT outputBegin, const stream_IT inputEnd, size_t messageLength, std::vector<source_T>& literals) const
{
using namespace internal;
Expand Down
4 changes: 2 additions & 2 deletions Utilities/rANS/include/rANS/LiteralEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ class LiteralEncoder : public Encoder<coder_T, stream_T, source_T>
using Encoder<coder_T, stream_T, source_T>::Encoder;

public:
template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool> = true>
const stream_IT process(const stream_IT outputBegin, const stream_IT outputEnd,
const source_IT inputBegin, source_IT inputEnd, std::vector<source_T>& literals) const;
};

template <typename coder_T, typename stream_T, typename source_T>
template <typename stream_IT, typename source_IT>
template <typename stream_IT, typename source_IT, std::enable_if_t<internal::isCompatibleIter_v<stream_T, stream_IT> && internal::isCompatibleIter_v<source_T, source_IT>, bool>>
const stream_IT LiteralEncoder<coder_T, stream_T, source_T>::process(const stream_IT outputBegin, const stream_IT outputEnd, const source_IT inputBegin, const source_IT inputEnd, std::vector<source_T>& literals) const
{
using namespace internal;
Expand Down
13 changes: 6 additions & 7 deletions Utilities/rANS/include/rANS/internal/Decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,21 @@ class Decoder

// Initializes a rANS decoder.
// Unlike the encoder, the decoder works forwards as you'd expect.
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool> = true>
Stream_IT init(Stream_IT iter);

// Returns the current cumulative frequency (map it to a symbol yourself!)
uint32_t get(uint32_t scale_bits);

// Equivalent to Rans32DecAdvance that takes a symbol.
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool> = true>
Stream_IT advanceSymbol(Stream_IT iter, const DecoderSymbol& sym, uint32_t scale_bits);

private:
State_T mState;

// Renormalize.
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool> = true>
std::tuple<State_T, Stream_IT> renorm(State_T x, Stream_IT iter);

// L ('l' in the paper) is the lower bound of our normalization interval.
Expand All @@ -79,10 +79,9 @@ template <typename State_T, typename Stream_T>
Decoder<State_T, Stream_T>::Decoder() : mState(0){};

template <typename State_T, typename Stream_T>
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool>>
Stream_IT Decoder<State_T, Stream_T>::init(Stream_IT iter)
{
static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value);

State_T x = 0;
Stream_IT streamPos = iter;
Expand Down Expand Up @@ -116,7 +115,7 @@ uint32_t Decoder<State_T, Stream_T>::get(uint32_t scale_bits)
};

template <typename State_T, typename Stream_T>
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool>>
Stream_IT Decoder<State_T, Stream_T>::advanceSymbol(Stream_IT iter, const DecoderSymbol& sym, uint32_t scale_bits)
{
static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value);
Expand All @@ -134,7 +133,7 @@ Stream_IT Decoder<State_T, Stream_T>::advanceSymbol(Stream_IT iter, const Decode
};

template <typename State_T, typename Stream_T>
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool>>
inline std::tuple<State_T, Stream_IT> Decoder<State_T, Stream_T>::renorm(State_T x, Stream_IT iter)
{
static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value);
Expand Down
21 changes: 8 additions & 13 deletions Utilities/rANS/include/rANS/internal/Encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,25 @@ class Encoder
// NOTE: With rANS, you need to encode symbols in *reverse order*, i.e. from
// beginning to end! Likewise, the output bytestream is written *backwards*:
// ptr starts pointing at the end of the output buffer and keeps decrementing.
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool> = true>
Stream_IT put(Stream_IT iter, uint32_t start, uint32_t freq, uint32_t scale_bits);

// Flushes the rANS encoder.
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool> = true>
Stream_IT flush(Stream_IT iter);

// Encodes a given symbol. This is faster than straight RansEnc since we can do
// multiplications instead of a divide.
//
// See Rans32EncSymbolInit for a description of how this works.
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool> = true>
Stream_IT putSymbol(Stream_IT iter, const EncoderSymbol<State_T>& sym, uint32_t scale_bits);

private:
State_T mState;

// Renormalize the encoder.
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool> = true>
std::tuple<State_T, Stream_IT> renorm(State_T x, Stream_IT iter, uint32_t freq, uint32_t scale_bits);

// L ('l' in the paper) is the lower bound of our normalization interval.
Expand All @@ -89,10 +89,9 @@ template <typename State_T, typename Stream_T>
Encoder<State_T, Stream_T>::Encoder() : mState(LOWER_BOUND){};

template <typename State_T, typename Stream_T>
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool>>
Stream_IT Encoder<State_T, Stream_T>::put(Stream_IT iter, uint32_t start, uint32_t freq, uint32_t scale_bits)
{
static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value);
// renormalize
Stream_IT streamPos;
State_T x;
Expand All @@ -104,10 +103,9 @@ Stream_IT Encoder<State_T, Stream_T>::put(Stream_IT iter, uint32_t start, uint32
};

template <typename State_T, typename Stream_T>
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool>>
Stream_IT Encoder<State_T, Stream_T>::flush(Stream_IT iter)
{
static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value);

Stream_IT streamPos = iter;

Expand All @@ -134,10 +132,9 @@ Stream_IT Encoder<State_T, Stream_T>::flush(Stream_IT iter)
};

template <typename State_T, typename Stream_T>
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool>>
Stream_IT Encoder<State_T, Stream_T>::putSymbol(Stream_IT iter, const EncoderSymbol<State_T>& sym, uint32_t scale_bits)
{
static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value);

assert(sym.freq != 0); // can't encode symbol with freq=0

Expand All @@ -163,11 +160,9 @@ Stream_IT Encoder<State_T, Stream_T>::putSymbol(Stream_IT iter, const EncoderSym
};

template <typename State_T, typename Stream_T>
template <typename Stream_IT>
template <typename Stream_IT, std::enable_if_t<isCompatibleIter_v<Stream_T, Stream_IT>, bool>>
inline std::tuple<State_T, Stream_IT> Encoder<State_T, Stream_T>::renorm(State_T x, Stream_IT iter, uint32_t freq, uint32_t scale_bits)
{
static_assert(std::is_same<typename std::iterator_traits<Stream_IT>::value_type, Stream_T>::value);

Stream_IT streamPos = iter;

State_T x_max = ((LOWER_BOUND >> scale_bits) << STREAM_BITS) * freq; // this turns into a shift.
Expand Down
5 changes: 5 additions & 0 deletions Utilities/rANS/include/rANS/internal/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include <cstddef>
#include <cmath>
#include <chrono>
#include <type_traits>
#include <iterator>

namespace o2
{
Expand Down Expand Up @@ -60,6 +62,9 @@ class RANSTimer
std::chrono::time_point<std::chrono::high_resolution_clock> mStop;
};

template <typename T, typename IT>
inline constexpr bool isCompatibleIter_v = std::is_same_v<typename std::iterator_traits<IT>::value_type, T>;

} // namespace internal
} // namespace rans
} // namespace o2
Expand Down

0 comments on commit 886a351

Please sign in to comment.