/*TITLE arithmetic encoding routines, no assembly */ /****keyword-flag*** "%v %f %n" */ /* "12 12-May-92,18:01:12 ARENC.C" */ #include "arith.h" #include "model.h" #include extern FILE *outfile; int buffer; int bits_to_go; unsigned low,high; unsigned bits_to_follow; #define bit_plus_follow_0 \ { \ output_0(); \ while (bits_to_follow > 0) \ { \ output_1(); \ bits_to_follow --; \ } \ } #define bit_plus_follow_1 \ { \ output_1(); \ while (bits_to_follow > 0) \ { \ output_0(); \ bits_to_follow --; \ } \ } int start_encoding() { low = 0; high = (unsigned)TOP_VALUE; bits_to_follow = 0; return(0); } int encode_symbol(unsigned symbol, unsigned oldch) { long range; unsigned i; unsigned cum; unsigned prev_cum; unsigned char *freq_ptr; int current_pair; unsigned char high_half; unsigned high_half_weight; unsigned total_pair_weight; unsigned total_freq; FrequencyInfo *temp_freq_info; temp_freq_info = frequency_info[oldch]; freq_ptr = temp_freq_info->freq; total_freq = temp_freq_info->total_freq; prev_cum = 0; for (i = 0; i < symbol/2; i ++) { current_pair = *(freq_ptr++); total_pair_weight = both_weights[current_pair]; prev_cum += total_pair_weight; } if (symbol % 2 == 0) /* if even, prev cum is ok, update cum */ { current_pair = *freq_ptr; high_half = (unsigned char)((current_pair & HIGH_MASK) >> HIGH_SHIFT); high_half_weight = translate[high_half]; cum = prev_cum + high_half_weight; } else /* if odd, update both */ { current_pair = *freq_ptr; total_pair_weight = both_weights[current_pair]; cum = prev_cum + total_pair_weight; high_half = (unsigned char)((current_pair & HIGH_MASK) >> HIGH_SHIFT); high_half_weight = translate[high_half]; prev_cum += high_half_weight; } /* end updating */ range = (long)(high-low)+1; high = low + (unsigned)((range * cum)/total_freq-1); low = low + (unsigned)((range * prev_cum)/total_freq); for (;;) { if (high < HALF) bit_plus_follow_0 else if (low >= HALF) { bit_plus_follow_1 low -= (unsigned)HALF; high -= (unsigned)HALF; } else if (low >= FIRST_QTR && high < THIRD_QTR) { bits_to_follow ++; low -= (unsigned)FIRST_QTR; high -= (unsigned)FIRST_QTR; } else break; low <<= 1; high <<= 1; high ++; } /* end of bit output loop */ return 0; } int done_encoding() { bits_to_follow ++; if (low < FIRST_QTR) bit_plus_follow_0 else bit_plus_follow_1 return(0); } int start_outputing_bits() { buffer = 0; bits_to_go = 8; return(0); } int output_0() { buffer >>= 1; bits_to_go --; if (bits_to_go == 0) { fputc(buffer,outfile); bits_to_go = 8; } return(0); } int output_1() { buffer >>= 1; buffer |= 0x80; bits_to_go --; if (bits_to_go == 0) { fputc(buffer,outfile); bits_to_go = 8; } return(0); } int done_outputing_bits() { fputc(buffer>>bits_to_go,outfile); return(0); }