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

/* cpair.c --- access category-pair constraint */

/* $Id: cpair.c,v 1.2 2002/09/11 22:01:50 ri Exp $ */

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

static unsigned char cp_table[] = {
  0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
};

/* get */
boolean
dfa_cp(DFA_INFO *dfa, int i, int j)
{
  int x,y;
  /*return(dfa->cp[i][j]);*/
  return((dfa->cp[i][j>>3] & cp_table[j&7]) ? TRUE : FALSE);
}

boolean
dfa_cp_begin(DFA_INFO *dfa, int i)
{
  /*return(dfa->cp_begin[i]);*/
  return((dfa->cp_begin[i>>3] & cp_table[i&7]) ? TRUE : FALSE);
}

boolean
dfa_cp_end(DFA_INFO *dfa, int i)
{
  /*return(dfa->cp_end[i]);*/
  return((dfa->cp_end[i>>3] & cp_table[i&7]) ? TRUE : FALSE);
}

/* set */
void
set_dfa_cp(DFA_INFO *dfa, int i, int j, boolean value)
{
  /*dfa->cp[i][j] = value;*/
  if (value) {
    dfa->cp[i][j>>3] |= cp_table[j&7];
  } else {
    dfa->cp[i][j>>3] &= ~ cp_table[j&7];
  }
}
void
set_dfa_cp_begin(DFA_INFO *dfa, int i, boolean value)
{
  /*dfa->cp_begin[i] = value;*/
  if (value) {
    dfa->cp_begin[i>>3] |= cp_table[i&7];
  } else {
    dfa->cp_begin[i>>3] &= ~ cp_table[i&7];
  }
}
void
set_dfa_cp_end(DFA_INFO *dfa, int i, boolean value)
{
  /*dfa->cp_end[i] = value;*/
  if (value) {
    dfa->cp_end[i>>3] |= cp_table[i&7];
  } else {
    dfa->cp_end[i>>3] &= ~ cp_table[i&7];
  }
}

/* init */
void
init_dfa_cp(DFA_INFO *dfa)
{
  dfa->cp_root = NULL;
  dfa->cp = NULL;
  dfa->cp_begin = NULL;
  dfa->cp_end = NULL;
}

/* allocate */
void
malloc_dfa_cp(DFA_INFO *dfa, int term_num)
{
  int i, j, x;

  x = (term_num + 7) >> 3;
  dfa->cp_root = (unsigned char *)mymalloc(sizeof(unsigned char) * term_num * x);
  dfa->cp = (unsigned char **)mymalloc(sizeof(unsigned char *) * term_num);
  for(i=0;i<term_num;i++) {
    dfa->cp[i] = &(dfa->cp_root[x*i]);
    for(j=0;j<term_num;j++) {
      set_dfa_cp(dfa, i, j, FALSE);
    }
  }
  dfa->cp_begin = (unsigned char *)mymalloc(sizeof(unsigned char) * x);
  dfa->cp_end = (unsigned char *)mymalloc(sizeof(unsigned char) * x);
  for(i=0;i<term_num;i++) {
    set_dfa_cp_begin(dfa, i, FALSE);
    set_dfa_cp_end(dfa, i, FALSE);
  }
  dfa->term_num = term_num;
}
/* re-allocate */
void
realloc_dfa_cp(DFA_INFO *dfa, int old_term_num, int new_term_num)
{
  int i, j, n, x, old_x;
  unsigned char *oldroot, *oldbegin, *oldend;
  unsigned char **oldcp;

  if (dfa->cp == NULL) return(malloc_dfa_cp(dfa, new_term_num));

  x = (new_term_num + 7) >> 3;
  old_x = (old_term_num + 7) >> 3;

  oldroot = dfa->cp_root;
  oldcp   = dfa->cp;
  
  dfa->cp_root = (unsigned char *)mymalloc(sizeof(unsigned char) * new_term_num * x);
  dfa->cp = (unsigned char **)mymalloc(sizeof(unsigned char *) * new_term_num);
  for(i=0;i<new_term_num;i++) {
    dfa->cp[i] = &(dfa->cp_root[x*i]);
  }
  for(i=0;i<old_term_num;i++) {
    for(n=0;n<old_x;n++) {
      dfa->cp[i][n] = oldcp[i][n];
    }
  }
  for(i=old_term_num;i<new_term_num;i++) {
    for(j=0;j<old_term_num;j++) {
      set_dfa_cp(dfa, i, j, FALSE);
      set_dfa_cp(dfa, j, i, FALSE);
    }
    set_dfa_cp(dfa, i, i, FALSE);
  }
  free(oldcp);
  free(oldroot);

  oldbegin = dfa->cp_begin;
  oldend = dfa->cp_end;
  dfa->cp_begin = (unsigned char *)mymalloc(sizeof(unsigned char) * x);
  dfa->cp_end = (unsigned char *)mymalloc(sizeof(unsigned char) * x);
  for(n=0;n<old_x;n++) {
    dfa->cp_begin[n] = oldbegin[n];
    dfa->cp_end[n] = oldend[n];
  }
  for(i=old_term_num;i<new_term_num;i++) {
    set_dfa_cp_begin(dfa, i, FALSE);
    set_dfa_cp_end(dfa, i, FALSE);
  }
  free(oldbegin);
  free(oldend);

  dfa->term_num = new_term_num;
}

/* free */
void
free_dfa_cp(DFA_INFO *dfa)
{
  if (dfa->cp != NULL) {
    free(dfa->cp_begin);
    free(dfa->cp_end);
    free(dfa->cp);
    free(dfa->cp_root);
  }
}
