home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-03-10 | 5.9 KB | 179 lines | [TEXT/ALFA] |
- // This may look like C code, but it is really -*- C++ -*-
- /*
- ************************************************************************
- *
- * Adaptive Arithmetic Coding
- * Adaptive model for the data source
- *
- * This is the implementation of the adaptive model based on the
- * Input_Data_Model.
- *
- * The present model is tailored to coding node values of the Laplacian
- * pyramid decomposition of gray-scale still images. The distribution of
- * the values is found (see laplpyr_hist.lst) to be almost ideally
- * modelled by the Lorentzian distribution with a very strong peak at
- * 0. This apriori information is coded into the frequency tables. As
- * symbols are processed, the frequency tables are updated (in the
- * way it is described in the book "Text Compression" referred to
- * elsewhere) to finely adjust the distribution. Note that re-scaling
- * of the frequencies is carried out more frequently than it is really
- * needed to prevent overflow in the coder. The reason is, rescaling of the
- * model makes it gradually forget what happened long ago, and tunes in the
- * model to the recent data. It makes sense if the ideal source model changes
- * with the time. It is certainly the case in the Laplacian pyramid,
- * where probability ditribution for different layers may be different.
- *
- * The program assumes the total no. of distinct input symbols
- * (integers) is relatively small, so simple linear arrays can be used
- * for storing and looking up the frequency tables.
- *
- * $Id: arithm_modadapt.cc,v 1.5 1995/05/31 16:23:24 oleg Exp oleg $
- *
- ************************************************************************
- */
-
- #pragma implementation "arithm_modadapt.h"
- #include "arithm_modadapt.h"
- #include "std.h"
-
- /*
- *------------------------------------------------------------------------
- * Constructors and Destructors
- */
-
- // Constructor
- AdaptiveModel::AdaptiveModel(const Symbol lwb, const Symbol upb)
- : symbol_lwb(lwb), symbol_upb(upb),
- no_symbols(upb-lwb+1)
- {
- assure(no_symbols > 1,
- "Bracketing interval for input symbols should include at least "
- "two symbols");
- allocate_model(no_symbols);
- symbol_to_index = new Index[no_symbols];
- // Note, indices range from 1 to EOF_index,
- // but EOF_index maps to no symbol
- index_to_symbol = new Symbol[no_symbols];
-
- initialize_model();
- }
-
- // Destructor
- AdaptiveModel::~AdaptiveModel()
- {
- assert( symbol_to_index != 0 && index_to_symbol != 0 );
- delete [] symbol_to_index;
- delete [] index_to_symbol;
- }
-
- // Initialize the model
- void AdaptiveModel::initialize_model(void)
- {
- // Set up the index vs. symbol mapping such
- // that symbol 0 would have index 1,
- // symbol 1 - index 2, symbol -1 - index 3,
- // etc.
- register int i;
- // Assume the symbol just in the middle is
- // most likely to occur
- register Symbol symbol = (symbol_lwb + symbol_upb)/2;
- register Index index;
- for(index=1,i=1; ;)
- {
- assert( symbol >= symbol_lwb && symbol <= symbol_upb );
- symbol_to_index[symbol-symbol_lwb] = index;
- index_to_symbol[index-1] = symbol;
-
- if( !(++index <= no_symbols) )
- break;
-
- while( abs(i) < 2*no_symbols )
- {
- symbol += i;
- i = ( i>0 ? -i-1 : -i+1 );
- if( symbol <= symbol_upb && symbol >= symbol_lwb )
- break;
- }
- assert( abs(i) < 2*no_symbols );
- }
-
- // Assign initial frequency counts
- // according to Lorentzian ditribution
- cum_frequencies[no_indices] = 0;
- for(i=no_indices; i>0; i--)
- {
- frequencies[i] = ( i == 1 ? 10*no_symbols : i <= 10 ? 10 : 1 );
- cum_frequencies[i-1] = cum_frequencies[i] + frequencies[i];
- }
- frequencies[0] = 0; // Must be zero to differ from freq[1]
- }
-
- /*
- *------------------------------------------------------------------------
- * Searching for index/symbol
- */
-
- // Return the index of a given symbol
- Index AdaptiveModel::get_index(const Symbol symbol) const
- {
- if( symbol < symbol_lwb || symbol > symbol_upb )
- _error("Symbol %d is out of interval [%d,%d]",
- symbol, symbol_lwb, symbol_upb);
- return symbol_to_index[symbol-symbol_lwb];
- }
-
- // Return the symbol for a given index
- Symbol AdaptiveModel::get_symbol(const Index index) const
- {
- if( index < 1 || index > no_symbols )
- _error("Index %d is out of boundaries [1,%d]",index,no_symbols);
- return index_to_symbol[index-1];
- }
-
- /*
- *------------------------------------------------------------------------
- * Update the adaptive model
- * to account for occurence of a particular index
- */
-
- void AdaptiveModel::update_model(const Index index)
- {
- if( total_cum_freq() >= Top_freq/4 ) // See if freq counts near their max
- { // /4 makes rescaling work more often
- register int cum = 0; // If so, halve all the counts
- register int i; // keeping them nonzero, and
- for(i=no_indices; i>=0; i--) // recompute the cumulative counts
- {
- cum_frequencies[i] = cum;
- cum += (frequencies[i] = (frequencies[i]+1) >> 1);
- }
- }
- // Try to pull 'index' to the beginning
- // of the freq. table, skipping symbols
- // with the same freq.
- register Lword * fp;
- for(fp = &frequencies[index]; *fp == *(fp-1); fp--)
- ; // Note, freq[0] never = freq[1]
- Index new_index = fp - frequencies; // Find a new position for the index
- if( new_index < index ) // If the index is to move, update
- { // the translation tables
- Symbol symbol_oind = index_to_symbol[index-1];
- Symbol symbol_nind = index_to_symbol[new_index-1];
- index_to_symbol[index-1] = symbol_nind;
- index_to_symbol[new_index-1] = symbol_oind;
- symbol_to_index[symbol_oind-symbol_lwb] = new_index;
- symbol_to_index[symbol_nind-symbol_lwb] = index;
- }
-
- // Note, the increment is large enough,
- const int update_inc = no_symbols/5 + 1; // since the count 1 acts like
- // -Infinity
- frequencies[new_index] += update_inc; // Increment the freq count for index
- register Lword * cfp; // And update the cumulative counts
- for(cfp=&cum_frequencies[new_index]; cfp>&cum_frequencies[0]; )
- *--cfp += update_inc;
- }
-
-
-
-