/*
* weights.c: Input of weights
*
* Written by: Ullrich Hafner
*
* This file is part of FIASCO (Fractal Image And Sequence COdec)
* Copyright (C) 1994-2000 Ullrich Hafner
*/
/*
* $Date: 2000/06/14 20:50:13 $
* $Author: hafner $
* $Revision: 5.1 $
* $State: Exp $
*/
#include "config.h"
#include "pm_c_util.h"
#include "types.h"
#include "macros.h"
#include "error.h"
#include "bit-io.h"
#include "arith.h"
#include "rpf.h"
#include "misc.h"
#include "weights.h"
/*****************************************************************************
public code
*****************************************************************************/
void
read_weights (unsigned total, wfa_t *wfa, bitfile_t *input)
/*
* Read #'total' weights from input stream 'input' and
* update transitions of the WFA states with corresponding weights.
*
* No return value.
*
* Side effects:
* 'wfa->weights' are filled with the decoded values
*/
{
unsigned state;
unsigned label;
unsigned edge; /* current edge */
unsigned *weights_array; /* array of weights to encode */
unsigned *level_array; /* array of corresponding levels */
unsigned offset1, offset2; /* prob. model offsets. */
unsigned offset3, offset4; /* prob. model offsets. */
bool_t delta_approx = NO; /* true if delta has been used */
/*
* 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)
*/
{
int min_level, max_level; /* min and max range level */
int d_min_level, d_max_level; /* min and max range level (delta) */
unsigned *lptr; /* pointer to current corresp. level */
int domain; /* current domain */
bool_t dc, d_dc; /* indicates whether DC is used */
/*
* Compute minimum and maximum level of delta and normal approximations
*/
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])
{
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;
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);
lptr = level_array = Calloc (total, sizeof (int));
for (state = wfa->basis_states; state < wfa->states; state++)
for (label = 0; label < MAXLABELS; label++)
if (isrange (wfa->tree[state][label]))
for (edge = 0; isedge (domain = wfa->into[state][label][edge]);
edge++)
{
if ((unsigned) (lptr - level_array) >= total)
error ("Can't read more than %d weights.", total);
if (domain)
{
if (delta_approx && wfa->delta_state [state])
*lptr++ = offset3 + wfa->level_of_state [state]
- 1 - d_min_level;
else
*lptr++ = offset2 + wfa->level_of_state [state]
- 1 - min_level;
}
else
*lptr++ = delta_approx && wfa->delta_state [state]
? offset1 : 0;
}
}
/*
* Decode the list of weights with an arithmetic decoder
*/
{
unsigned i;
unsigned *c_symbols = Calloc (offset4, sizeof (unsigned));
const unsigned 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);
weights_array = decode_array (input, level_array, c_symbols,
offset4, total, scale);
Free (c_symbols);
}
Free (level_array);
/*
* Update transitions with decoded weights
*/
{
unsigned *wptr = weights_array; /* pointer to current weight */
int domain; /* current domain */
for (state = wfa->basis_states; state < wfa->states; state++)
for (label = 0; label < MAXLABELS; label++)
if (isrange (wfa->tree[state][label]))
for (edge = 0; isedge (domain = wfa->into[state][label][edge]);
edge++)
{
if (domain) /* not DC component */
{
if (delta_approx && wfa->delta_state [state])
wfa->weight [state][label][edge]
= btor (*wptr++, wfa->wfainfo->d_rpf);
else
wfa->weight [state][label][edge]
= btor (*wptr++, wfa->wfainfo->rpf);
}
else
{
if (delta_approx && wfa->delta_state [state])
wfa->weight [state][label][edge]
= btor (*wptr++, wfa->wfainfo->d_dc_rpf);
else
wfa->weight [state][label][edge]
= btor (*wptr++, wfa->wfainfo->dc_rpf);
}
wfa->int_weight [state][label][edge]
= wfa->weight [state][label][edge] * 512 + 0.5;
}
}
Free (weights_array);
}