246 lines
7.3 KiB
C++
246 lines
7.3 KiB
C++
// 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_2_
|
|
#define DLIB_ENTROPY_DECODER_MODEL_KERNEl_2_
|
|
|
|
#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,
|
|
typename ccbig
|
|
>
|
|
class entropy_decoder_model_kernel_2
|
|
{
|
|
/*!
|
|
REQUIREMENTS ON cc
|
|
cc is an implementation of conditioning_class/conditioning_class_kernel_abstract.h
|
|
cc::get_alphabet_size() == alphabet_size+1
|
|
this will be used for the order-0 context
|
|
|
|
REQUIREMENTS ON ccbig
|
|
ccbig is an implementation of conditioning_class/conditioning_class_kernel_abstract.h
|
|
ccbig::get_alphabet_size() == alphabet_size+1
|
|
this will be used for the order-1 context
|
|
|
|
INITIAL VALUE
|
|
Initially this object's finite context model is empty
|
|
previous_symbol == 0
|
|
|
|
CONVENTION
|
|
&get_entropy_decoder() == coder
|
|
&order_0.get_global_state() == &gs
|
|
&order_1[i]->get_global_state() == &gsbig
|
|
|
|
|
|
This is an order-1-0 model. The last symbol in the order-0 and order-1
|
|
context is an escape into the lower context.
|
|
|
|
previous_symbol == the last symbol seen
|
|
!*/
|
|
|
|
public:
|
|
|
|
typedef entropy_decoder entropy_decoder_type;
|
|
|
|
entropy_decoder_model_kernel_2 (
|
|
entropy_decoder& coder
|
|
);
|
|
|
|
virtual ~entropy_decoder_model_kernel_2 (
|
|
);
|
|
|
|
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;
|
|
typename ccbig::global_state_type gsbig;
|
|
cc order_0;
|
|
ccbig* order_1[alphabet_size];
|
|
unsigned long previous_symbol;
|
|
|
|
|
|
// restricted functions
|
|
entropy_decoder_model_kernel_2(entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>&); // copy constructor
|
|
entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>& operator=(entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>&); // assignment operator
|
|
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
// member function definitions
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
unsigned long alphabet_size,
|
|
typename entropy_decoder,
|
|
typename cc,
|
|
typename ccbig
|
|
>
|
|
entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>::
|
|
entropy_decoder_model_kernel_2 (
|
|
entropy_decoder& coder_
|
|
) :
|
|
coder(coder_),
|
|
order_0(gs),
|
|
previous_symbol(0)
|
|
{
|
|
COMPILE_TIME_ASSERT( 1 < alphabet_size && alphabet_size < 65535);
|
|
|
|
unsigned long i;
|
|
try
|
|
{
|
|
for (i = 0; i < alphabet_size; ++i)
|
|
{
|
|
order_1[i] = new ccbig(gsbig);
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
for (unsigned long j = 0; j < i; ++j)
|
|
{
|
|
delete order_1[j];
|
|
}
|
|
throw;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
unsigned long alphabet_size,
|
|
typename entropy_decoder,
|
|
typename cc,
|
|
typename ccbig
|
|
>
|
|
entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>::
|
|
~entropy_decoder_model_kernel_2 (
|
|
)
|
|
{
|
|
for (unsigned long i = 0; i < alphabet_size; ++i)
|
|
{
|
|
delete order_1[i];
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
unsigned long alphabet_size,
|
|
typename entropy_decoder,
|
|
typename cc,
|
|
typename ccbig
|
|
>
|
|
void entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>::
|
|
clear(
|
|
)
|
|
{
|
|
previous_symbol = 0;
|
|
order_0.clear();
|
|
for (unsigned long i = 0; i < alphabet_size; ++i)
|
|
{
|
|
order_1[i]->clear();
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
unsigned long alphabet_size,
|
|
typename entropy_decoder,
|
|
typename cc,
|
|
typename ccbig
|
|
>
|
|
void entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>::
|
|
decode (
|
|
unsigned long& symbol
|
|
)
|
|
{
|
|
unsigned long current_symbol, low_count, high_count, target;
|
|
|
|
// look in the order-1 context
|
|
target = coder.get_target(order_1[previous_symbol]->get_total());
|
|
order_1[previous_symbol]->get_symbol(target,current_symbol,low_count,high_count);
|
|
|
|
// have the coder decode the next symbol
|
|
coder.decode(low_count,high_count);
|
|
|
|
// if the current_symbol is not an escape from the order-1 context
|
|
if (current_symbol != alphabet_size)
|
|
{
|
|
symbol = current_symbol;
|
|
order_1[previous_symbol]->increment_count(current_symbol,2);
|
|
previous_symbol = current_symbol;
|
|
return;
|
|
}
|
|
|
|
// since this is an escape to order-0 we should increment
|
|
// the escape symbol
|
|
order_1[previous_symbol]->increment_count(alphabet_size);
|
|
|
|
|
|
|
|
// 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_1[previous_symbol]->increment_count(current_symbol,2);
|
|
order_0.increment_count(current_symbol,2);
|
|
|
|
symbol = current_symbol;
|
|
previous_symbol = current_symbol;
|
|
return;
|
|
}
|
|
|
|
// update the count for the escape symbol
|
|
order_0.increment_count(current_symbol);
|
|
|
|
|
|
// go into the order minus one context
|
|
target = coder.get_target(alphabet_size);
|
|
coder.decode(target,target+1);
|
|
|
|
|
|
// update the count for this symbol
|
|
order_1[previous_symbol]->increment_count(target,2);
|
|
order_0.increment_count(target,2);
|
|
|
|
symbol = target;
|
|
previous_symbol = target;
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // DLIB_ENTROPY_DECODER_MODEL_KERNEl_2_
|
|
|