/*TITLE adaptive modeling routines */ /****keyword-flag*** "%v %f %n" */ /* "16 30-May-94,9:24:34 ADAPT.C" */ #include #include "model.h" #define INIT_INDEX 7 /* where a new character starts out the first time */ #define BOTH_WEIGHTS_ZERO 2 /* this must be the total of two "unused" weights */ /* and must be the same for both (or all) translate tables */ unsigned translate[TRANSLATE_SIZE] = TRANSLATE_TABLE; unsigned char upgrade_threshold[TRANSLATE_SIZE]; /* all possible combinations of 2 low weights */ unsigned both_weights[TRANSLATE_SIZE*TRANSLATE_SIZE]; unsigned symbol_translation[NO_OF_CHARS] = {32,101,116,111,97,105,110,114,115, 104,108,100,13,10,99,117,109,112,103,121,102,46,98,119,44,94,118,107,78,84, 69,39,65,83,41,40,120,66,45,73,34,77,58,80,85,67,49,82,48,87,79,47,88,72, 70,68,89,57,71,113,76,50,86,122,106,59,63,54,55,74,61,42,37,12,53,64,56,75, 33,52,51,90,62,38,81,35,26,255,254,253,252,251,250,249,248,247,246,245,244, 243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225, 224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206, 205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187, 186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168, 167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149, 148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130, 129,128,127,126,125,124,123,96,95,93,92,91,60,43,36,31,30,29,28,27,25,24,23, 22,21,20,19,18,17,16,15,14,11,9,8,7,6,5,4,3,2,1,0}; unsigned char_translation[NO_OF_CHARS]; FrequencyInfo frequency_info_data[NO_OF_CHARS]; FrequencyInfo *frequency_info[NO_OF_CHARS]; unsigned char char_total; start_model() { int i; int j; double temp_threshold; for (i = 0; i < TRANSLATE_SIZE - 1; i ++) { temp_threshold = 256*(1-(double)translate[i]/(double)translate[i+1]); upgrade_threshold[i] = (unsigned char)temp_threshold; } upgrade_threshold[TRANSLATE_SIZE-1] = 255; char_total = 0; for (i = 0; i < TRANSLATE_SIZE; i ++) for (j = 0; j < TRANSLATE_SIZE; j ++) both_weights[TRANSLATE_SIZE*i+j] = translate[i] + translate[j]; for (i = 0; i < NO_OF_CHARS; i ++) { frequency_info[i] = &frequency_info_data[i]; for (j = 0; j < (NO_OF_SYMBOLS+1+1)/2; j ++) frequency_info[i]->freq[j] = 0; frequency_info[i]->total_freq = translate[0] * (NO_OF_SYMBOLS + 1); } for (i = 0; i < NO_OF_CHARS; i ++) char_translation[symbol_translation[i]] = i; return(0); } update_model(int symbol,unsigned char oldch) { int i; int index; unsigned char *freq_ptr; unsigned char freq; int old_weight_code; unsigned weight_gain; unsigned char temp_freq; long temp_total_freq; FrequencyInfo *temp_freq_info; unsigned char low_symbol; low_symbol = (unsigned char)(symbol_translation[symbol] & 255); char_total = (unsigned char)(char_total + low_symbol); old_weight_code = -1; temp_freq_info = frequency_info[oldch]; freq_ptr = temp_freq_info->freq; index = symbol/2; if (symbol % 2 == 0) /* if a high symbol */ { temp_freq = (unsigned char)((freq_ptr[index] & HIGH_MASK) >> HIGH_SHIFT); if (temp_freq == 0) { freq_ptr[index] += INIT_INDEX << HIGH_SHIFT; temp_freq_info->total_freq += translate[INIT_INDEX] - translate[0]; } else if (char_total > upgrade_threshold[temp_freq]) { old_weight_code = temp_freq; freq_ptr[index] += HIGH_INCREMENT; /* bump it */ } } else /* if a low one */ { temp_freq = (unsigned char)((freq_ptr[index] & LOW_MASK) >> LOW_SHIFT); if (temp_freq == 0) { freq_ptr[index] += INIT_INDEX << LOW_SHIFT; temp_freq_info->total_freq += translate[INIT_INDEX] - translate[0]; } else if (char_total > upgrade_threshold[temp_freq]) { old_weight_code = temp_freq; freq_ptr[index] += LOW_INCREMENT; /* bump it */ } } if (old_weight_code != -1) /* if there was an adjustment of weight */ { weight_gain = translate[old_weight_code+1] - translate[old_weight_code]; temp_freq_info->total_freq += weight_gain; } temp_total_freq = temp_freq_info->total_freq; while (temp_total_freq > MAX_FREQUENCY) { temp_total_freq = 0; freq_ptr = temp_freq_info->freq; for (i = 0; i < (NO_OF_SYMBOLS+1)/2; i ++) { if (*freq_ptr == 0) /* if this is at the bottom, forget it */ temp_total_freq += BOTH_WEIGHTS_ZERO; else /* if it needs to be updated */ { freq = *freq_ptr; if ((freq & HIGH_MASK) != 0) { /* if the top is not at the lowest value*/ *freq_ptr -= HIGH_INCREMENT; /* decrement it */ } if ((freq & LOW_MASK) != 0) { /* if the low is not at the lowest value*/ *freq_ptr -= LOW_INCREMENT; /* decrement it */ } temp_total_freq += both_weights[*freq_ptr]; } freq_ptr ++; } } temp_freq_info->total_freq = (unsigned)temp_total_freq; return(0); }