// 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_