39.45 model_1ee.c

/*  
 * model_1e.c  
 *  
 * Un modelo probabilístico de orden 1, inicialmente vacío, con  
 * exclusión de símbolos.  
 *  
 * Referencias:  
 *  
 * model_0.c  
 * model_0s.c  
 * model_1s.c  
 * model_1e.c  
 * Witten, Neal, and Cleary, CACM, 1987.  
 * M. Nelson and J.-L. Gailly, The Data Compression Book. 1995.  
 */  
 
#include <stdio.h>  
#include "vlc.h"  
#include "codec.h"  
#include "model_1e.h"  
 
#include "model_0/find_symbols_and_indexes.h"  
 
void compute_cumulative_probs(unsigned short *prob,  
                              unsigned short *cum_prob) {  
  int i;  
  int cum = 0;  
  for(i=ALPHA_SIZE; i>=0; i--) {  
    cum_prob[i] = cum;  
    cum += prob[i];  
  }  
}  
 
#define _symbol_to_index _symbol_to_index[context]  
#define _index_to_symbol _index_to_symbol[context]  
#define prob prob[context]  
#define cum_prob cum_prob[context]  
#include "model_1e/scale_probs.h"  
#include "model_0/increment_prob_of_index.h"  
#include "model_0/test_if_scale.h"  
#include "model_0/update_model.h"  
#undef _index_to_symbol  
#undef _symbol_to_index  
#undef cum_prob  
#undef prob  
 
#include "model_1e/init_model.h"  
#include "model_0/finish_model.h"  
 
/* Tiene en cuenta los símbolos que han aparecido en "context" para  
   calcular las probabilidades acumuladas en el contexto "ESC". */  
void exclude_symbols(int context,  
                     unsigned short *cum_prob) {  
  unsigned short new_prob[ALPHA_SIZE+1];  
  int i;  
  for(i=0; i<ALPHA_SIZE+1; i++) {  
    new_prob[i] = prob[ESC][i];  
    if(prob[context][i]) {  
      new_prob[i] = 0;  
    }  
  }  
  compute_cumulative_probs(new_prob, cum_prob);  
}  
 
void encode_stream() {  
  context = ESC;  
  init_model();  
  init_encoder();  
  for(;;) {  
    symbol = getchar();  
    if (symbol==EOF) break;  
    index = find_index(symbol);  
    if(prob[context][index]) {  
      encode(index, cum_prob[context]);  
    } else {  
      unsigned short new_cum_prob[ALPHA_SIZE+1];  
      encode(ESC_index, cum_prob[context]);  
      index = find_index(symbol);  
      /* Calculamos un nuevo espacio de probabilidades, sabiendo que  
         ninguno de los símbolos contemplados por el el contexto  
         "context" es el símbolo a codificar "symbol". De esta forma,  
         incrementamos la probabilidad del símbolo codificado. */  
      exclude_symbols(context, new_cum_prob);  
      encode(index, new_cum_prob);  
    }  
    update_model();  
    context = symbol;  
  }  
  encode(EOS_index, cum_prob[context]);  
  finish_encoder();  
  finish_model();  
}  
 
void decode_stream() {  
  context = ESC;  
  init_model();  
  init_decoder();  
  for(;;) {  
    index = decode(cum_prob[context]);  
    if(index==EOS_index) break;  
    symbol = find_symbol(index);  
    if(symbol==ESC) {  
      unsigned short new_cum_prob[ALPHA_SIZE+1];  
      exclude_symbols(context, new_cum_prob);  
      index = decode(new_cum_prob);  
      symbol = find_symbol(index);  
    }  
    putchar(symbol);  
    update_model();  
    context = symbol;  
  }  
  finish_decoder();  
  finish_model();  
}