void write_tree (const wfa_t *wfa, bitfile_t *output) /* * Write bintree to stream 'output'. * Traverse tree in breadth first order and save a '1' for each child * and a '0' for each range image. * * No return value. */ { unsigned queue [MAXSTATES]; /* state numbers in BFO */ unsigned current; /* current node to process */ unsigned last; /* last node (update every new node) */ unsigned label; /* current label */ int into; /* next child */ byte_t *tree_string; /* bitstring to encode */ unsigned total = 0; /* number of ranges */ unsigned bits = bits_processed (output); /* number of bits */ /* * Traverse tree in breadth first order. Use a queue to store * the childs of each node ('last' is the next free queue element). * The first element ('current') of this queue will get the new parent * node. */ tree_string = Calloc (MAXSTATES * MAXLABELS, sizeof (byte_t)); queue [0] = wfa->root_state; for (last = 1, current = 0; current < last; current++) for (label = 0; label < MAXLABELS; label++) if (!isrange (into = wfa->tree [queue[current]][label])) /* child ? */ { queue [last++] = into; tree_string [total++] = 1; } else /* or range ? */ tree_string [total++] = 0; if (total != (wfa->states - wfa->basis_states) * MAXLABELS) error ("total [%d] != (states - basis_states) * 2 [%d]", total, (wfa->states - wfa->basis_states) * MAXLABELS); { unsigned scale = total / 20 ; encode_tree (output, tree_string, total, scale, 1, 11); } Free (tree_string); debug_message ("tree: %5d bits. (%5d symbols => %5.2f bps)", bits_processed (output) - bits, total, total > 0 ? ((bits_processed (output) - bits) / (double) total) : 0); }
void write_weights (unsigned total, const wfa_t *wfa, bitfile_t *output) /* * Traverse the transition matrices of the 'wfa' and write #'total' * weights != 0 to stream 'output'. * * No return value. */ { unsigned state, label; /* current label */ unsigned offset1, offset2; /* model offsets. */ unsigned offset3, offset4; /* model offsets. */ unsigned *weights_array; /* array of weights to encode */ unsigned *wptr; /* pointer to current weight */ unsigned *level_array; /* array of corresponding levels */ unsigned *lptr; /* pointer to current corr. level */ int min_level, max_level; /* min and max range level */ int d_min_level, d_max_level; /* min and max delta range level */ bool_t dc, d_dc; /* true if dc or delta dc are used */ bool_t delta_approx = NO; /* true if delta has been used */ unsigned delta_count = 0; /* number of delta ranges */ unsigned bits = bits_processed (output); /* * Check whether delta approximation has been used */ for (state = wfa->basis_states; state < wfa->states; state++) if (wfa->delta_state [state]) { delta_approx = YES; break; } /* * Generate array of corresponding levels (context of probability model) */ min_level = d_min_level = MAXLEVEL; max_level = d_max_level = 0; dc = d_dc = NO; for (state = wfa->basis_states; state < wfa->states; state++) for (label = 0; label < MAXLABELS; label++) if (isrange (wfa->tree [state][label])) { if (delta_approx && wfa->delta_state [state]) /* delta approx. */ { d_min_level = min (d_min_level, wfa->level_of_state [state] - 1); d_max_level = max (d_max_level, wfa->level_of_state [state] - 1); if (wfa->into [state][label][0] == 0) d_dc = YES; } else { min_level = min (min_level, wfa->level_of_state [state] - 1); max_level = max (max_level, wfa->level_of_state [state] - 1); if (wfa->into [state][label][0] == 0) dc = YES; } } if (min_level > max_level) /* no lc found */ max_level = min_level - 1; if (d_min_level > d_max_level) d_max_level = d_min_level - 1; /* * Context model: * 0 DC weight * 1 Delta DC weight * 2-k normal weights per level * k+1 - m Delta weights per level */ offset1 = dc ? 1 : 0; offset2 = offset1 + (d_dc ? 1 : 0); offset3 = offset2 + (max_level - min_level + 1); offset4 = offset3 + (d_max_level - d_min_level + 1); /* * Weights are encoded as follows: * all weights of state n * sorted by label * sorted by domain number */ wptr = weights_array = Calloc (total, sizeof (unsigned)); lptr = level_array = Calloc (total, sizeof (unsigned)); for (state = wfa->basis_states; state < wfa->states; state++) for (label = 0; label < MAXLABELS; label++) if (isrange (wfa->tree [state][label])) { int edge; /* current edge */ int domain; /* current domain (context of model) */ for (edge = 0; isedge (domain = wfa->into [state][label][edge]); edge++) { if (wptr - weights_array >= (int) total) error ("Can't write more than %d weights.", total); if (domain) /* not DC component */ { if (delta_approx && wfa->delta_state [state]) /* delta */ { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->d_rpf); *lptr++ = offset3 + wfa->level_of_state [state] - 1 - d_min_level; delta_count++; } else { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->rpf); *lptr++ = offset2 + wfa->level_of_state [state] - 1 - min_level; } } else /* DC component */ { if (delta_approx && wfa->delta_state [state]) /* delta */ { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->d_dc_rpf); *lptr++ = offset1; } else { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->dc_rpf); *lptr++ = 0; } } } } { unsigned i; unsigned *c_symbols = Calloc (offset4, sizeof (int)); const int scale = 500; /* scaling of probability model */ c_symbols [0] = 1 << (wfa->wfainfo->dc_rpf->mantissa_bits + 1); if (offset1 != offset2) c_symbols [offset1] = 1 << (wfa->wfainfo->d_dc_rpf->mantissa_bits + 1); for (i = offset2; i < offset3; i++) c_symbols [i] = 1 << (wfa->wfainfo->rpf->mantissa_bits + 1); for (; i < offset4; i++) c_symbols [i] = 1 << (wfa->wfainfo->d_rpf->mantissa_bits + 1); encode_array (output, weights_array, level_array, c_symbols, offset4, total, scale); Free (c_symbols); } debug_message ("%d delta weights out of %d.", delta_count, total); debug_message ("weights: %5d bits. (%5d symbols => %5.2f bps)", bits_processed (output) - bits, total, (bits_processed (output) - bits) / (double) total); Free (weights_array); Free (level_array); }