// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_MODEL_KERNEl_1_
#define DLIB_ENTROPY_DECODER_MODEL_KERNEl_1_
#include "../algs.h"
#include "entropy_decoder_model_kernel_abstract.h"
#include "../assert.h"
namespace dlib
{
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc
>
class entropy_decoder_model_kernel_1
{
/*!
REQUIREMENTS ON cc
cc is an implementation of conditioning_class/conditioning_class_kernel_abstract.h
cc::get_alphabet_size() == alphabet_size+1
INITIAL VALUE
Initially this object's finite context model is empty
CONVENTION
&get_entropy_decoder() == coder
&order_0.get_global_state() == &gs
This is an order-0 model. The last symbol in the order-0 context is
an escape into the order minus 1 context.
!*/
public:
typedef entropy_decoder entropy_decoder_type;
entropy_decoder_model_kernel_1 (
entropy_decoder& coder
);
virtual ~entropy_decoder_model_kernel_1 (
);
inline void clear(
);
inline void decode (
unsigned long& symbol
);
entropy_decoder& get_entropy_decoder (
) { return coder; }
static unsigned long get_alphabet_size (
) { return alphabet_size; }
private:
entropy_decoder& coder;
typename cc::global_state_type gs;
cc order_0;
// restricted functions
entropy_decoder_model_kernel_1(entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>&); // copy constructor
entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>& operator=(entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc
>
entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>::
entropy_decoder_model_kernel_1 (
entropy_decoder& coder_
) :
coder(coder_),
order_0(gs)
{
COMPILE_TIME_ASSERT( 1 < alphabet_size && alphabet_size < 65535 );
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc
>
entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>::
~entropy_decoder_model_kernel_1 (
)
{
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc
>
void entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>::
clear(
)
{
order_0.clear();
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc
>
void entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>::
decode (
unsigned long& symbol
)
{
unsigned long current_symbol, low_count, high_count, target;
// look in the order-0 context
target = coder.get_target(order_0.get_total());
order_0.get_symbol(target,current_symbol,low_count,high_count);
// have coder decode the next symbol
coder.decode(low_count,high_count);
// if current_symbol is not an escape from the order-0 context
if (current_symbol != alphabet_size)
{
// update the count for this symbol
order_0.increment_count(current_symbol,2);
symbol = current_symbol;
return;
}
// update the count for the escape symbol
order_0.increment_count(alphabet_size);
// go into the order minus one context
target = coder.get_target(alphabet_size);
coder.decode(target,target+1);
// update the count for this symbol in the order-0 context
order_0.increment_count(target,2);
symbol = target;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ENTROPY_DECODER_MODEL_KERNEl_1_