/* Copyright (c) 1991-2002 Doshita Lab. Speech Group, Kyoto University */
/* Copyright (c) 2000-2002 Speech and Acoustics Processing Lab., NAIST */
/*   All rights reserved   */

/* mkcpair.c --- extract category-pair constraint from DFA */

/* $Id: mkcpair.c,v 1.6 2003/01/06 08:05:37 ri Exp $ */

#include <sent/stddefs.h>
#include <sent/dfa.h>

/* extract category-pair constraint from DFA */
/* short pause words (sp) are skipped */
/* DFA is for 2nd pass (right-to-left), and
   category-pair is for 1st pass, so
   arc from initial state in dfa corresponds to cp_end, and
   arc  to  accept  state in dfa corresponds to cp_begin */
/* assume that skippable short pause (sp) should not appear in
   beginning and end of sentence (use silB or silE instead) */
void
extract_cpair(DFA_INFO *dinfo)
{
  int i,j;
  DFA_ARC *arc_l, *arc_r, *arc_r2;
  int left, right;

  /* initialize */
  malloc_dfa_cp(dinfo, dinfo->term_num);

  /* extract cpair info */
  for (i=0;i<dinfo->state_num;i++) {
    if ((dinfo->st[i].status & INITIAL_S) != 0) { /* arc from initial state */
      for (arc_r = dinfo->st[i].arc; arc_r; arc_r = arc_r->next) {
	if (dinfo->is_sp[arc_r->label]) {
	  j_error("Error: skippable sp should not appear at end of sentence\n");
	}
	set_dfa_cp_end(dinfo, arc_r->label, TRUE);
      }
    }
    for(arc_l = dinfo->st[i].arc; arc_l; arc_l = arc_l->next) {
      left = arc_l->label;
      if ((dinfo->st[arc_l->to_state].status & ACCEPT_S) != 0) {/* arc to accept state */
	if (dinfo->is_sp[left]) {
	  j_error("Error: skippable sp should not appear at beginning of sentence\n");
	}
	set_dfa_cp_begin(dinfo, left, TRUE);
      }
      /* others */
      for (arc_r = dinfo->st[arc_l->to_state].arc; arc_r; arc_r = arc_r->next) {
	right = arc_r->label;
	set_dfa_cp(dinfo, right, left, TRUE);
	if (dinfo->is_sp[right]) {
	  for (arc_r2 = dinfo->st[arc_r->to_state].arc; arc_r2; arc_r2 = arc_r2->next) {
	    if (dinfo->is_sp[arc_r2->label]) { /* sp model continues twice */
	      j_error("Error: skippable sp should not repeat\n");
	    }
	    set_dfa_cp(dinfo, arc_r2->label, left, TRUE);
	  }
	}
      }

    }
  }
}

void
cpair_append(DFA_INFO *dst, DFA_INFO *src, int coffset)
{
  int i,j;

  /* dst info must be already appended */
  /* [coffset..dst->term_num-1] is the new categories */
  if (dst->term_num - coffset != src->term_num) {
    j_error("InternalError: append term num not match!: %d, %d, %d\n",
	    dst->term_num, src->term_num, coffset);
  }

  /* allocate appended area */
  realloc_dfa_cp(dst, coffset, dst->term_num);
  
  /* append cp */
  for(i=coffset;i<dst->term_num;i++) {
    for(j=coffset;j<dst->term_num;j++) {
      set_dfa_cp(dst, i, j, dfa_cp(src, i-coffset, j-coffset));
    }
    set_dfa_cp_begin(dst, i, dfa_cp_begin(src, i-coffset));
    set_dfa_cp_end(dst, i, dfa_cp_end(src, i-coffset));
  }
}
