diff options
Diffstat (limited to 'media/pocketsphinx/src/hmm.c')
-rw-r--r-- | media/pocketsphinx/src/hmm.c | 825 |
1 files changed, 825 insertions, 0 deletions
diff --git a/media/pocketsphinx/src/hmm.c b/media/pocketsphinx/src/hmm.c new file mode 100644 index 000000000..73b2c98cc --- /dev/null +++ b/media/pocketsphinx/src/hmm.c @@ -0,0 +1,825 @@ +/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* ==================================================================== + * Copyright (c) 1999-2004 Carnegie Mellon University. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * This work was supported in part by funding from the Defense Advanced + * Research Projects Agency and the National Science Foundation of the + * United States of America, and the CMU Sphinx Speech Consortium. + * + * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND + * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY + * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ==================================================================== + * + */ + +/** + * @file hmm.h Implementation of HMM base structure. + */ + +/* System headers. */ +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> + +/* SphinxBase headers. */ +#include <sphinxbase/ckd_alloc.h> +#include <sphinxbase/err.h> + +/* Local headers. */ +#include "hmm.h" + +hmm_context_t * +hmm_context_init(int32 n_emit_state, + uint8 ** const *tp, + int16 const *senscore, + uint16 * const *sseq) +{ + hmm_context_t *ctx; + + assert(n_emit_state > 0); + if (n_emit_state > HMM_MAX_NSTATE) { + E_ERROR("Number of emitting states must be <= %d\n", HMM_MAX_NSTATE); + return NULL; + } + + ctx = ckd_calloc(1, sizeof(*ctx)); + ctx->n_emit_state = n_emit_state; + ctx->tp = tp; + ctx->senscore = senscore; + ctx->sseq = sseq; + ctx->st_sen_scr = ckd_calloc(n_emit_state, sizeof(*ctx->st_sen_scr)); + + return ctx; +} + +void +hmm_context_free(hmm_context_t *ctx) +{ + if (ctx == NULL) + return; + ckd_free(ctx->st_sen_scr); + ckd_free(ctx); +} + +void +hmm_init(hmm_context_t *ctx, hmm_t *hmm, int mpx, int ssid, int tmatid) +{ + hmm->ctx = ctx; + hmm->mpx = mpx; + hmm->n_emit_state = ctx->n_emit_state; + if (mpx) { + int i; + hmm->ssid = BAD_SSID; + hmm->senid[0] = ssid; + for (i = 1; i < hmm_n_emit_state(hmm); ++i) { + hmm->senid[i] = BAD_SSID; + } + } + else { + hmm->ssid = ssid; + memcpy(hmm->senid, ctx->sseq[ssid], hmm->n_emit_state * sizeof(*hmm->senid)); + } + hmm->tmatid = tmatid; + hmm_clear(hmm); +} + +void +hmm_deinit(hmm_t *hmm) +{ +} + +void +hmm_dump(hmm_t * hmm, + FILE * fp) +{ + int32 i; + + if (hmm_is_mpx(hmm)) { + fprintf(fp, "MPX "); + for (i = 0; i < hmm_n_emit_state(hmm); i++) + fprintf(fp, " %11d", hmm_senid(hmm, i)); + fprintf(fp, " ( "); + for (i = 0; i < hmm_n_emit_state(hmm); i++) + fprintf(fp, "%d ", hmm_ssid(hmm, i)); + fprintf(fp, ")\n"); + } + else { + fprintf(fp, "SSID "); + for (i = 0; i < hmm_n_emit_state(hmm); i++) + fprintf(fp, " %11d", hmm_senid(hmm, i)); + fprintf(fp, " (%d)\n", hmm_ssid(hmm, 0)); + } + + if (hmm->ctx->senscore) { + fprintf(fp, "SENSCR"); + for (i = 0; i < hmm_n_emit_state(hmm); i++) + fprintf(fp, " %11d", hmm_senscr(hmm, i)); + fprintf(fp, "\n"); + } + + fprintf(fp, "SCORES %11d", hmm_in_score(hmm)); + for (i = 1; i < hmm_n_emit_state(hmm); i++) + fprintf(fp, " %11d", hmm_score(hmm, i)); + fprintf(fp, " %11d", hmm_out_score(hmm)); + fprintf(fp, "\n"); + + fprintf(fp, "HISTID %11d", hmm_in_history(hmm)); + for (i = 1; i < hmm_n_emit_state(hmm); i++) + fprintf(fp, " %11d", hmm_history(hmm, i)); + fprintf(fp, " %11d", hmm_out_history(hmm)); + fprintf(fp, "\n"); + + if (hmm_in_score(hmm) > 0) + fprintf(fp, + "ALERT!! The input score %d is large than 0. Probably wrap around.\n", + hmm_in_score(hmm)); + if (hmm_out_score(hmm) > 0) + fprintf(fp, + "ALERT!! The output score %d is large than 0. Probably wrap around\n.", + hmm_out_score(hmm)); + + fflush(fp); +} + + +void +hmm_clear_scores(hmm_t * h) +{ + int32 i; + + hmm_in_score(h) = WORST_SCORE; + for (i = 1; i < hmm_n_emit_state(h); i++) + hmm_score(h, i) = WORST_SCORE; + hmm_out_score(h) = WORST_SCORE; + + h->bestscore = WORST_SCORE; +} + +void +hmm_clear(hmm_t * h) +{ + int32 i; + + hmm_in_score(h) = WORST_SCORE; + hmm_in_history(h) = -1; + for (i = 1; i < hmm_n_emit_state(h); i++) { + hmm_score(h, i) = WORST_SCORE; + hmm_history(h, i) = -1; + } + hmm_out_score(h) = WORST_SCORE; + hmm_out_history(h) = -1; + + h->bestscore = WORST_SCORE; + h->frame = -1; +} + +void +hmm_enter(hmm_t *h, int32 score, int32 histid, int frame) +{ + hmm_in_score(h) = score; + hmm_in_history(h) = histid; + hmm_frame(h) = frame; +} + +void +hmm_normalize(hmm_t *h, int32 bestscr) +{ + int32 i; + + for (i = 0; i < hmm_n_emit_state(h); i++) { + if (hmm_score(h, i) BETTER_THAN WORST_SCORE) + hmm_score(h, i) -= bestscr; + } + if (hmm_out_score(h) BETTER_THAN WORST_SCORE) + hmm_out_score(h) -= bestscr; +} + +#define hmm_tprob_5st(i, j) (-tp[(i)*6+(j)]) +#define nonmpx_senscr(i) (-senscore[sseq[i]]) + +static int32 +hmm_vit_eval_5st_lr(hmm_t * hmm) +{ + int16 const *senscore = hmm->ctx->senscore; + uint8 const *tp = hmm->ctx->tp[hmm->tmatid][0]; + uint16 const *sseq = hmm->senid; + int32 s5, s4, s3, s2, s1, s0, t2, t1, t0, bestScore; + + /* It was the best of scores, it was the worst of scores. */ + bestScore = WORST_SCORE; + + /* Cache problem here! */ + s4 = hmm_score(hmm, 4) + nonmpx_senscr(4); + s3 = hmm_score(hmm, 3) + nonmpx_senscr(3); + /* Transitions into non-emitting state 5 */ + if (s3 BETTER_THAN WORST_SCORE) { + t1 = s4 + hmm_tprob_5st(4, 5); + t2 = s3 + hmm_tprob_5st(3, 5); + if (t1 BETTER_THAN t2) { + s5 = t1; + hmm_out_history(hmm) = hmm_history(hmm, 4); + } else { + s5 = t2; + hmm_out_history(hmm) = hmm_history(hmm, 3); + } + if (s5 WORSE_THAN WORST_SCORE) s5 = WORST_SCORE; + hmm_out_score(hmm) = s5; + bestScore = s5; + } + + s2 = hmm_score(hmm, 2) + nonmpx_senscr(2); + /* All transitions into state 4 */ + if (s2 BETTER_THAN WORST_SCORE) { + t0 = s4 + hmm_tprob_5st(4, 4); + t1 = s3 + hmm_tprob_5st(3, 4); + t2 = s2 + hmm_tprob_5st(2, 4); + if (t0 BETTER_THAN t1) { + if (t2 BETTER_THAN t0) { + s4 = t2; + hmm_history(hmm, 4) = hmm_history(hmm, 2); + } else + s4 = t0; + } else { + if (t2 BETTER_THAN t1) { + s4 = t2; + hmm_history(hmm, 4) = hmm_history(hmm, 2); + } else { + s4 = t1; + hmm_history(hmm, 4) = hmm_history(hmm, 3); + } + } + if (s4 WORSE_THAN WORST_SCORE) s4 = WORST_SCORE; + if (s4 BETTER_THAN bestScore) bestScore = s4; + hmm_score(hmm, 4) = s4; + } + + s1 = hmm_score(hmm, 1) + nonmpx_senscr(1); + /* All transitions into state 3 */ + if (s1 BETTER_THAN WORST_SCORE) { + t0 = s3 + hmm_tprob_5st(3, 3); + t1 = s2 + hmm_tprob_5st(2, 3); + t2 = s1 + hmm_tprob_5st(1, 3); + if (t0 BETTER_THAN t1) { + if (t2 BETTER_THAN t0) { + s3 = t2; + hmm_history(hmm, 3) = hmm_history(hmm, 1); + } else + s3 = t0; + } else { + if (t2 BETTER_THAN t1) { + s3 = t2; + hmm_history(hmm, 3) = hmm_history(hmm, 1); + } else { + s3 = t1; + hmm_history(hmm, 3) = hmm_history(hmm, 2); + } + } + if (s3 WORSE_THAN WORST_SCORE) s3 = WORST_SCORE; + if (s3 BETTER_THAN bestScore) bestScore = s3; + hmm_score(hmm, 3) = s3; + } + + s0 = hmm_in_score(hmm) + nonmpx_senscr(0); + /* All transitions into state 2 (state 0 is always active) */ + t0 = s2 + hmm_tprob_5st(2, 2); + t1 = s1 + hmm_tprob_5st(1, 2); + t2 = s0 + hmm_tprob_5st(0, 2); + if (t0 BETTER_THAN t1) { + if (t2 BETTER_THAN t0) { + s2 = t2; + hmm_history(hmm, 2) = hmm_in_history(hmm); + } else + s2 = t0; + } else { + if (t2 BETTER_THAN t1) { + s2 = t2; + hmm_history(hmm, 2) = hmm_in_history(hmm); + } else { + s2 = t1; + hmm_history(hmm, 2) = hmm_history(hmm, 1); + } + } + if (s2 WORSE_THAN WORST_SCORE) s2 = WORST_SCORE; + if (s2 BETTER_THAN bestScore) bestScore = s2; + hmm_score(hmm, 2) = s2; + + + /* All transitions into state 1 */ + t0 = s1 + hmm_tprob_5st(1, 1); + t1 = s0 + hmm_tprob_5st(0, 1); + if (t0 BETTER_THAN t1) { + s1 = t0; + } else { + s1 = t1; + hmm_history(hmm, 1) = hmm_in_history(hmm); + } + if (s1 WORSE_THAN WORST_SCORE) s1 = WORST_SCORE; + if (s1 BETTER_THAN bestScore) bestScore = s1; + hmm_score(hmm, 1) = s1; + + /* All transitions into state 0 */ + s0 = s0 + hmm_tprob_5st(0, 0); + if (s0 WORSE_THAN WORST_SCORE) s0 = WORST_SCORE; + if (s0 BETTER_THAN bestScore) bestScore = s0; + hmm_in_score(hmm) = s0; + + hmm_bestscore(hmm) = bestScore; + return bestScore; +} + +#define mpx_senid(st) sseq[ssid[st]][st] +#define mpx_senscr(st) (-senscore[mpx_senid(st)]) + +static int32 +hmm_vit_eval_5st_lr_mpx(hmm_t * hmm) +{ + uint8 const *tp = hmm->ctx->tp[hmm->tmatid][0]; + int16 const *senscore = hmm->ctx->senscore; + uint16 * const *sseq = hmm->ctx->sseq; + uint16 *ssid = hmm->senid; + int32 bestScore; + int32 s5, s4, s3, s2, s1, s0, t2, t1, t0; + + /* Don't propagate WORST_SCORE */ + if (ssid[4] == BAD_SSID) + s4 = t1 = WORST_SCORE; + else { + s4 = hmm_score(hmm, 4) + mpx_senscr(4); + t1 = s4 + hmm_tprob_5st(4, 5); + } + if (ssid[3] == BAD_SSID) + s3 = t2 = WORST_SCORE; + else { + s3 = hmm_score(hmm, 3) + mpx_senscr(3); + t2 = s3 + hmm_tprob_5st(3, 5); + } + if (t1 BETTER_THAN t2) { + s5 = t1; + hmm_out_history(hmm) = hmm_history(hmm, 4); + } + else { + s5 = t2; + hmm_out_history(hmm) = hmm_history(hmm, 3); + } + if (s5 WORSE_THAN WORST_SCORE) s5 = WORST_SCORE; + hmm_out_score(hmm) = s5; + bestScore = s5; + + /* Don't propagate WORST_SCORE */ + if (ssid[2] == BAD_SSID) + s2 = t2 = WORST_SCORE; + else { + s2 = hmm_score(hmm, 2) + mpx_senscr(2); + t2 = s2 + hmm_tprob_5st(2, 4); + } + + t0 = t1 = WORST_SCORE; + if (s4 != WORST_SCORE) + t0 = s4 + hmm_tprob_5st(4, 4); + if (s3 != WORST_SCORE) + t1 = s3 + hmm_tprob_5st(3, 4); + if (t0 BETTER_THAN t1) { + if (t2 BETTER_THAN t0) { + s4 = t2; + hmm_history(hmm, 4) = hmm_history(hmm, 2); + ssid[4] = ssid[2]; + } + else + s4 = t0; + } + else { + if (t2 BETTER_THAN t1) { + s4 = t2; + hmm_history(hmm, 4) = hmm_history(hmm, 2); + ssid[4] = ssid[2]; + } + else { + s4 = t1; + hmm_history(hmm, 4) = hmm_history(hmm, 3); + ssid[4] = ssid[3]; + } + } + if (s4 WORSE_THAN WORST_SCORE) s4 = WORST_SCORE; + if (s4 BETTER_THAN bestScore) + bestScore = s4; + hmm_score(hmm, 4) = s4; + + /* Don't propagate WORST_SCORE */ + if (ssid[1] == BAD_SSID) + s1 = t2 = WORST_SCORE; + else { + s1 = hmm_score(hmm, 1) + mpx_senscr(1); + t2 = s1 + hmm_tprob_5st(1, 3); + } + t0 = t1 = WORST_SCORE; + if (s3 != WORST_SCORE) + t0 = s3 + hmm_tprob_5st(3, 3); + if (s2 != WORST_SCORE) + t1 = s2 + hmm_tprob_5st(2, 3); + if (t0 BETTER_THAN t1) { + if (t2 BETTER_THAN t0) { + s3 = t2; + hmm_history(hmm, 3) = hmm_history(hmm, 1); + ssid[3] = ssid[1]; + } + else + s3 = t0; + } + else { + if (t2 BETTER_THAN t1) { + s3 = t2; + hmm_history(hmm, 3) = hmm_history(hmm, 1); + ssid[3] = ssid[1]; + } + else { + s3 = t1; + hmm_history(hmm, 3) = hmm_history(hmm, 2); + ssid[3] = ssid[2]; + } + } + if (s3 WORSE_THAN WORST_SCORE) s3 = WORST_SCORE; + if (s3 BETTER_THAN bestScore) bestScore = s3; + hmm_score(hmm, 3) = s3; + + /* State 0 is always active */ + s0 = hmm_in_score(hmm) + mpx_senscr(0); + + /* Don't propagate WORST_SCORE */ + t0 = t1 = WORST_SCORE; + if (s2 != WORST_SCORE) + t0 = s2 + hmm_tprob_5st(2, 2); + if (s1 != WORST_SCORE) + t1 = s1 + hmm_tprob_5st(1, 2); + t2 = s0 + hmm_tprob_5st(0, 2); + if (t0 BETTER_THAN t1) { + if (t2 BETTER_THAN t0) { + s2 = t2; + hmm_history(hmm, 2) = hmm_in_history(hmm); + ssid[2] = ssid[0]; + } + else + s2 = t0; + } + else { + if (t2 BETTER_THAN t1) { + s2 = t2; + hmm_history(hmm, 2) = hmm_in_history(hmm); + ssid[2] = ssid[0]; + } + else { + s2 = t1; + hmm_history(hmm, 2) = hmm_history(hmm, 1); + ssid[2] = ssid[1]; + } + } + if (s2 WORSE_THAN WORST_SCORE) s2 = WORST_SCORE; + if (s2 BETTER_THAN bestScore) bestScore = s2; + hmm_score(hmm, 2) = s2; + + /* Don't propagate WORST_SCORE */ + t0 = WORST_SCORE; + if (s1 != WORST_SCORE) + t0 = s1 + hmm_tprob_5st(1, 1); + t1 = s0 + hmm_tprob_5st(0, 1); + if (t0 BETTER_THAN t1) { + s1 = t0; + } + else { + s1 = t1; + hmm_history(hmm, 1) = hmm_in_history(hmm); + ssid[1] = ssid[0]; + } + if (s1 WORSE_THAN WORST_SCORE) s1 = WORST_SCORE; + if (s1 BETTER_THAN bestScore) bestScore = s1; + hmm_score(hmm, 1) = s1; + + s0 += hmm_tprob_5st(0, 0); + if (s0 WORSE_THAN WORST_SCORE) s0 = WORST_SCORE; + if (s0 BETTER_THAN bestScore) bestScore = s0; + hmm_in_score(hmm) = s0; + + hmm_bestscore(hmm) = bestScore; + return bestScore; +} + +#define hmm_tprob_3st(i, j) (-tp[(i)*4+(j)]) + +static int32 +hmm_vit_eval_3st_lr(hmm_t * hmm) +{ + int16 const *senscore = hmm->ctx->senscore; + uint8 const *tp = hmm->ctx->tp[hmm->tmatid][0]; + uint16 const *sseq = hmm->senid; + int32 s3, s2, s1, s0, t2, t1, t0, bestScore; + + s2 = hmm_score(hmm, 2) + nonmpx_senscr(2); + s1 = hmm_score(hmm, 1) + nonmpx_senscr(1); + s0 = hmm_in_score(hmm) + nonmpx_senscr(0); + + /* It was the best of scores, it was the worst of scores. */ + bestScore = WORST_SCORE; + t2 = INT_MIN; /* Not used unless skipstate is true */ + + /* Transitions into non-emitting state 3 */ + if (s1 BETTER_THAN WORST_SCORE) { + t1 = s2 + hmm_tprob_3st(2, 3); + if (hmm_tprob_3st(1,3) BETTER_THAN TMAT_WORST_SCORE) + t2 = s1 + hmm_tprob_3st(1, 3); + if (t1 BETTER_THAN t2) { + s3 = t1; + hmm_out_history(hmm) = hmm_history(hmm, 2); + } else { + s3 = t2; + hmm_out_history(hmm) = hmm_history(hmm, 1); + } + if (s3 WORSE_THAN WORST_SCORE) s3 = WORST_SCORE; + hmm_out_score(hmm) = s3; + bestScore = s3; + } + + /* All transitions into state 2 (state 0 is always active) */ + t0 = s2 + hmm_tprob_3st(2, 2); + t1 = s1 + hmm_tprob_3st(1, 2); + if (hmm_tprob_3st(0, 2) BETTER_THAN TMAT_WORST_SCORE) + t2 = s0 + hmm_tprob_3st(0, 2); + if (t0 BETTER_THAN t1) { + if (t2 BETTER_THAN t0) { + s2 = t2; + hmm_history(hmm, 2) = hmm_in_history(hmm); + } else + s2 = t0; + } else { + if (t2 BETTER_THAN t1) { + s2 = t2; + hmm_history(hmm, 2) = hmm_in_history(hmm); + } else { + s2 = t1; + hmm_history(hmm, 2) = hmm_history(hmm, 1); + } + } + if (s2 WORSE_THAN WORST_SCORE) s2 = WORST_SCORE; + if (s2 BETTER_THAN bestScore) bestScore = s2; + hmm_score(hmm, 2) = s2; + + /* All transitions into state 1 */ + t0 = s1 + hmm_tprob_3st(1, 1); + t1 = s0 + hmm_tprob_3st(0, 1); + if (t0 BETTER_THAN t1) { + s1 = t0; + } else { + s1 = t1; + hmm_history(hmm, 1) = hmm_in_history(hmm); + } + if (s1 WORSE_THAN WORST_SCORE) s1 = WORST_SCORE; + if (s1 BETTER_THAN bestScore) bestScore = s1; + hmm_score(hmm, 1) = s1; + + /* All transitions into state 0 */ + s0 = s0 + hmm_tprob_3st(0, 0); + if (s0 WORSE_THAN WORST_SCORE) s0 = WORST_SCORE; + if (s0 BETTER_THAN bestScore) bestScore = s0; + hmm_in_score(hmm) = s0; + + hmm_bestscore(hmm) = bestScore; + return bestScore; +} + +static int32 +hmm_vit_eval_3st_lr_mpx(hmm_t * hmm) +{ + uint8 const *tp = hmm->ctx->tp[hmm->tmatid][0]; + int16 const *senscore = hmm->ctx->senscore; + uint16 * const *sseq = hmm->ctx->sseq; + uint16 *ssid = hmm->senid; + int32 bestScore; + int32 s3, s2, s1, s0, t2, t1, t0; + + /* Don't propagate WORST_SCORE */ + t2 = INT_MIN; /* Not used unless skipstate is true */ + if (ssid[2] == BAD_SSID) + s2 = t1 = WORST_SCORE; + else { + s2 = hmm_score(hmm, 2) + mpx_senscr(2); + t1 = s2 + hmm_tprob_3st(2, 3); + } + if (ssid[1] == BAD_SSID) + s1 = t2 = WORST_SCORE; + else { + s1 = hmm_score(hmm, 1) + mpx_senscr(1); + if (hmm_tprob_3st(1,3) BETTER_THAN TMAT_WORST_SCORE) + t2 = s1 + hmm_tprob_3st(1, 3); + } + if (t1 BETTER_THAN t2) { + s3 = t1; + hmm_out_history(hmm) = hmm_history(hmm, 2); + } + else { + s3 = t2; + hmm_out_history(hmm) = hmm_history(hmm, 1); + } + if (s3 WORSE_THAN WORST_SCORE) s3 = WORST_SCORE; + hmm_out_score(hmm) = s3; + bestScore = s3; + + /* State 0 is always active */ + s0 = hmm_in_score(hmm) + mpx_senscr(0); + + /* Don't propagate WORST_SCORE */ + t0 = t1 = WORST_SCORE; + if (s2 != WORST_SCORE) + t0 = s2 + hmm_tprob_3st(2, 2); + if (s1 != WORST_SCORE) + t1 = s1 + hmm_tprob_3st(1, 2); + if (hmm_tprob_3st(0,2) BETTER_THAN TMAT_WORST_SCORE) + t2 = s0 + hmm_tprob_3st(0, 2); + if (t0 BETTER_THAN t1) { + if (t2 BETTER_THAN t0) { + s2 = t2; + hmm_history(hmm, 2) = hmm_in_history(hmm); + ssid[2] = ssid[0]; + } + else + s2 = t0; + } + else { + if (t2 BETTER_THAN t1) { + s2 = t2; + hmm_history(hmm, 2) = hmm_in_history(hmm); + ssid[2] = ssid[0]; + } + else { + s2 = t1; + hmm_history(hmm, 2) = hmm_history(hmm, 1); + ssid[2] = ssid[1]; + } + } + if (s2 WORSE_THAN WORST_SCORE) s2 = WORST_SCORE; + if (s2 BETTER_THAN bestScore) bestScore = s2; + hmm_score(hmm, 2) = s2; + + /* Don't propagate WORST_SCORE */ + t0 = WORST_SCORE; + if (s1 != WORST_SCORE) + t0 = s1 + hmm_tprob_3st(1, 1); + t1 = s0 + hmm_tprob_3st(0, 1); + if (t0 BETTER_THAN t1) { + s1 = t0; + } + else { + s1 = t1; + hmm_history(hmm, 1) = hmm_in_history(hmm); + ssid[1] = ssid[0]; + } + if (s1 WORSE_THAN WORST_SCORE) s1 = WORST_SCORE; + if (s1 BETTER_THAN bestScore) bestScore = s1; + hmm_score(hmm, 1) = s1; + + /* State 0 is always active */ + s0 += hmm_tprob_3st(0, 0); + if (s0 WORSE_THAN WORST_SCORE) s0 = WORST_SCORE; + if (s0 BETTER_THAN bestScore) bestScore = s0; + hmm_in_score(hmm) = s0; + + hmm_bestscore(hmm) = bestScore; + return bestScore; +} + +static int32 +hmm_vit_eval_anytopo(hmm_t * hmm) +{ + hmm_context_t *ctx = hmm->ctx; + int32 to, from, bestfrom; + int32 newscr, scr, bestscr; + int final_state; + + /* Compute previous state-score + observation output prob for each emitting state */ + ctx->st_sen_scr[0] = hmm_in_score(hmm) + hmm_senscr(hmm, 0); + for (from = 1; from < hmm_n_emit_state(hmm); ++from) { + if ((ctx->st_sen_scr[from] = + hmm_score(hmm, from) + hmm_senscr(hmm, from)) WORSE_THAN WORST_SCORE) + ctx->st_sen_scr[from] = WORST_SCORE; + } + + /* FIXME/TODO: Use the BLAS for all this. */ + /* Evaluate final-state first, which does not have a self-transition */ + final_state = hmm_n_emit_state(hmm); + to = final_state; + scr = WORST_SCORE; + bestfrom = -1; + for (from = to - 1; from >= 0; --from) { + if ((hmm_tprob(hmm, from, to) BETTER_THAN TMAT_WORST_SCORE) && + ((newscr = ctx->st_sen_scr[from] + + hmm_tprob(hmm, from, to)) BETTER_THAN scr)) { + scr = newscr; + bestfrom = from; + } + } + hmm_out_score(hmm) = scr; + if (bestfrom >= 0) + hmm_out_history(hmm) = hmm_history(hmm, bestfrom); + bestscr = scr; + + /* Evaluate all other states, which might have self-transitions */ + for (to = final_state - 1; to >= 0; --to) { + /* Score from self-transition, if any */ + scr = + (hmm_tprob(hmm, to, to) BETTER_THAN TMAT_WORST_SCORE) + ? ctx->st_sen_scr[to] + hmm_tprob(hmm, to, to) + : WORST_SCORE; + + /* Scores from transitions from other states */ + bestfrom = -1; + for (from = to - 1; from >= 0; --from) { + if ((hmm_tprob(hmm, from, to) BETTER_THAN TMAT_WORST_SCORE) && + ((newscr = ctx->st_sen_scr[from] + + hmm_tprob(hmm, from, to)) BETTER_THAN scr)) { + scr = newscr; + bestfrom = from; + } + } + + /* Update new result for state to */ + if (to == 0) { + hmm_in_score(hmm) = scr; + if (bestfrom >= 0) + hmm_in_history(hmm) = hmm_history(hmm, bestfrom); + } + else { + hmm_score(hmm, to) = scr; + if (bestfrom >= 0) + hmm_history(hmm, to) = hmm_history(hmm, bestfrom); + } + /* Propagate ssid for multiplex HMMs */ + if (bestfrom >= 0 && hmm_is_mpx(hmm)) + hmm->senid[to] = hmm->senid[bestfrom]; + + if (bestscr WORSE_THAN scr) + bestscr = scr; + } + + hmm_bestscore(hmm) = bestscr; + return bestscr; +} + +int32 +hmm_vit_eval(hmm_t * hmm) +{ + if (hmm_is_mpx(hmm)) { + if (hmm_n_emit_state(hmm) == 5) + return hmm_vit_eval_5st_lr_mpx(hmm); + else if (hmm_n_emit_state(hmm) == 3) + return hmm_vit_eval_3st_lr_mpx(hmm); + else + return hmm_vit_eval_anytopo(hmm); + } + else { + if (hmm_n_emit_state(hmm) == 5) + return hmm_vit_eval_5st_lr(hmm); + else if (hmm_n_emit_state(hmm) == 3) + return hmm_vit_eval_3st_lr(hmm); + else + return hmm_vit_eval_anytopo(hmm); + } +} + +int32 +hmm_dump_vit_eval(hmm_t * hmm, FILE * fp) +{ + int32 bs = 0; + + if (fp) { + fprintf(fp, "BEFORE:\n"); + hmm_dump(hmm, fp); + } + bs = hmm_vit_eval(hmm); + if (fp) { + fprintf(fp, "AFTER:\n"); + hmm_dump(hmm, fp); + } + + return bs; +} |