/* * control.c: Control unit of WFA structure * * 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:51 $ * $Author: hafner $ * $Revision: 5.1 $ * $State: Exp $ */ #include "config.h" #include #include "types.h" #include "macros.h" #include "error.h" #include "cwfa.h" #include "ip.h" #include "misc.h" #include "wfalib.h" #include "control.h" /***************************************************************************** prototypes *****************************************************************************/ static void clear_or_alloc (real_t **ptr, size_t size); static void compute_images (unsigned from, unsigned to, const wfa_t *wfa, coding_t *c); /***************************************************************************** public code *****************************************************************************/ void append_state (bool_t auxiliary_state, real_t final, unsigned level_of_state, wfa_t *wfa, coding_t *c) /* * Append a 'wfa' state. If 'auxiliary_state' == YES then * allocate memory for inner products and state images. 'final' is * the final distribution of the new state. 'level_of_state' is the * level of the subimage which is represented by this state * * No return value. * * Side effects: * The WFA information are updated in structure 'wfa' * State images are computed and inner products are cleared (in 'c') */ { wfa->final_distribution [wfa->states] = final; wfa->level_of_state [wfa->states] = level_of_state; if (!auxiliary_state) { unsigned level; wfa->domain_type [wfa->states] = USE_DOMAIN_MASK; /* * Allocate memory for inner products and for state images */ clear_or_alloc (&c->images_of_state [wfa->states], size_of_tree (c->options.images_level)); for (level = c->options.images_level + 1; level <= c->options.lc_max_level; level++) clear_or_alloc (&c->ip_states_state [wfa->states][level], wfa->states + 1); clear_or_alloc (&c->ip_images_state [wfa->states], size_of_tree (c->products_level)); /* * Compute the images of the current state at level 0,..,'imageslevel' */ c->images_of_state [wfa->states][0] = final; compute_images (wfa->states, wfa->states, wfa, c); /* * Compute the inner products between the current state and the * old states 0,...,'states'-1 */ compute_ip_states_state (wfa->states, wfa->states, wfa, c); } else { unsigned level; wfa->domain_type [wfa->states] = 0; /* * Free the allocated memory */ if (c->images_of_state [wfa->states] != NULL) { Free (c->images_of_state [wfa->states]); c->images_of_state [wfa->states] = NULL; } for (level = 0; level <= c->options.lc_max_level; level++) if (c->ip_states_state [wfa->states][level]) { Free (c->ip_states_state [wfa->states][level]); c->ip_states_state [wfa->states][level] = NULL; } if (c->ip_images_state [wfa->states]) { Free (c->ip_images_state [wfa->states]); c->ip_images_state [wfa->states] = NULL; } } wfa->states++; if (wfa->states >= MAXSTATES) error ("Maximum number of states reached!"); } void append_basis_states (unsigned basis_states, wfa_t *wfa, coding_t *c) /* * Append the WFA basis states 0, ... , ('basis_states' - 1). * * No return value. * * Side effects: * The WFA information are updated in structure 'wfa' * State images and inner products are computed (in 'c') */ { unsigned level, state; /* * Allocate memory */ for (state = 0; state < basis_states; state++) { clear_or_alloc (&c->images_of_state [state], size_of_tree (c->options.images_level)); for (level = c->options.images_level + 1; level <= c->options.lc_max_level; level++) clear_or_alloc (&c->ip_states_state [state][level], state + 1); clear_or_alloc (&c->ip_images_state [state], size_of_tree (c->products_level)); c->images_of_state [state][0] = wfa->final_distribution [state]; wfa->level_of_state [state] = -1; } compute_images (0, basis_states - 1, wfa, c); compute_ip_states_state (0, basis_states - 1, wfa, c); wfa->states = basis_states; if (wfa->states >= MAXSTATES) error ("Maximum number of states reached!"); } void append_transitions (unsigned state, unsigned label, const real_t *weight, const word_t *into, wfa_t *wfa) /* * Append the 'wfa' transitions (given by the arrays 'weight' and 'into') * of the range ('state','label'). * * No return value. * * Side effects: * new 'wfa' edges are appended */ { unsigned edge; wfa->y_column [state][label] = 0; for (edge = 0; isedge (into [edge]); edge++) { append_edge (state, into [edge], weight [edge], label, wfa); if (into [edge] == wfa->y_state [state][label]) wfa->y_column [state][label] = 1; } } /***************************************************************************** private code *****************************************************************************/ static void compute_images (unsigned from, unsigned to, const wfa_t *wfa, coding_t *c) /* * Computes the images of the given states 'from', ... , 'to' * at level 0,...,'c->imagelevel'. * Uses the fact that each state image is a linear combination of state * images, i.e. s_i := c_0 s_0 + ... + c_i s_i. */ { unsigned label, level, state; /* * Compute the images Phi(state) * # level = 0 * ## level = 1 * #### level = 2 * ######## level = 3 * ... * ########...## level = imageslevel */ for (level = 1; level <= c->options.images_level; level++) for (state = from; state <= to; state++) for (label = 0; label < MAXLABELS; label++) { real_t *dst, *src; unsigned edge; int domain; /* current domain */ if (ischild (domain = wfa->tree[state][label])) { dst = c->images_of_state [state] + address_of_level (level) + label * size_of_level (level - 1); src = c->images_of_state [domain] + address_of_level (level - 1); memcpy (dst, src, size_of_level (level - 1) * sizeof (real_t)); } for (edge = 0; isedge (domain = wfa->into[state][label][edge]); edge++) { unsigned n; real_t weight = wfa->weight [state][label][edge]; dst = c->images_of_state [state] + address_of_level (level) + label * size_of_level (level - 1); src = c->images_of_state [domain] + address_of_level (level - 1); for (n = size_of_level (level - 1); n; n--) *dst++ += *src++ * weight; } } } static void clear_or_alloc (real_t **ptr, size_t size) /* * if *ptr == NULL allocate memory with Calloc * otherwise fill the real_t-array ptr[] with 0 */ { if (*ptr == NULL) *ptr = Calloc (size, sizeof (real_t)); else memset (*ptr, 0, size * sizeof (real_t)); }