Пример #1
0
static int
expand_rule(jsgf_t * grammar, jsgf_rule_t * rule, int rule_entry,
            int rule_exit)
{
    jsgf_rule_stack_t *rule_stack_entry;
    jsgf_rhs_t *rhs;

    /* Push this rule onto the stack */
    rule_stack_entry =
        (jsgf_rule_stack_t *) ckd_calloc(1, sizeof(jsgf_rule_stack_t));
    rule_stack_entry->rule = rule;
    rule_stack_entry->entry = rule_entry;
    grammar->rulestack = glist_add_ptr(grammar->rulestack,
                                       rule_stack_entry);

    for (rhs = rule->rhs; rhs; rhs = rhs->alt) {
        int lastnode;

        lastnode = expand_rhs(grammar, rule, rhs, rule_entry, rule_exit);

        if (lastnode == NO_NODE) {
            return NO_NODE;
        }
        else if (lastnode == RECURSIVE_NODE) {
            /* The rhs ended with right-recursion, i.e. a transition to
               an earlier state. Nothing needs to happen at this level. */
            ;
        }
        else if (rule_exit == NO_NODE) {
            /* If this rule doesn't have an exit state yet, use the exit
               state of its first right-hand-side.
               All other right-hand-sides will use this exit state. */
            assert(lastnode >= 0);
            rule_exit = lastnode;
        }
    }

    /* If no exit-state was created, use the entry-state. */
    if (rule_exit == NO_NODE) {
        rule_exit = rule_entry;
    }

    /* Pop this rule from the rule stack */
    ckd_free(gnode_ptr(grammar->rulestack));
    grammar->rulestack = gnode_free(grammar->rulestack, NULL);

    return rule_exit;
}
Пример #2
0
static int
expand_rule(jsgf_t *grammar, jsgf_rule_t *rule)
{
    jsgf_rhs_t *rhs;
    float norm;

    /* Push this rule onto the stack */
    grammar->rulestack = glist_add_ptr(grammar->rulestack, rule);

    /* Normalize weights for all alternatives exiting rule->entry */
    norm = 0;
    for (rhs = rule->rhs; rhs; rhs = rhs->alt) {
        if (rhs->atoms) {
            jsgf_atom_t *atom = gnode_ptr(rhs->atoms);
            norm += atom->weight;
        }
    }

    rule->entry = grammar->nstate++;
    rule->exit = grammar->nstate++;
    if (norm == 0) norm = 1;
    for (rhs = rule->rhs; rhs; rhs = rhs->alt) {
        int lastnode;

        if (rhs->atoms) {
            jsgf_atom_t *atom = gnode_ptr(rhs->atoms);
	    atom->weight /= norm;
        }
        lastnode = expand_rhs(grammar, rule, rhs);
        if (lastnode == -1) {
            return -1;
        }
        else {
            jsgf_add_link(grammar, NULL, lastnode, rule->exit);
        }
    }

    /* Pop this rule from the rule stack */
    grammar->rulestack = gnode_free(grammar->rulestack, NULL);
    return rule->exit;
}
Пример #3
0
static void
huff_code_canonicalize(huff_code_t *hc, huff_node_t *root)
{
    glist_t agenda;
    uint32 *nextcode;
    int i, ncw;

    hc->firstcode =(uint32*) ckd_calloc(hc->maxbits+1, sizeof(*hc->firstcode));
    hc->syms = (huff_codeword_t**)ckd_calloc(hc->maxbits+1, sizeof(*hc->syms));
    hc->numl =(uint32*) ckd_calloc(hc->maxbits+1, sizeof(*nextcode));
    nextcode =(uint32*) ckd_calloc(hc->maxbits+1, sizeof(*nextcode));

    /* Traverse the tree, annotating it with the actual bit
     * lengths, and histogramming them in numl. */
    root->nbits = 0;
    ncw = 0;
    agenda = glist_add_ptr(0, root);
    while (agenda) {
        huff_node_t *node = (huff_node_t*)gnode_ptr(agenda);
        agenda = gnode_free(agenda, 0);
        if (node->l) {
            node->l->nbits = node->nbits + 1;
            agenda = glist_add_ptr(agenda, node->l);
            node->r.r->nbits = node->nbits + 1;
            agenda = glist_add_ptr(agenda, node->r.r);
        }
        else {
            hc->numl[node->nbits]++;
            ncw++;
        }
    }
    /* Create starting codes and symbol tables for each bit length. */
    hc->syms[hc->maxbits] = (huff_codeword_t*)ckd_calloc(hc->numl[hc->maxbits], sizeof(**hc->syms));
    for (i = hc->maxbits - 1; i > 0; --i) {
        hc->firstcode[i] = (hc->firstcode[i+1] + hc->numl[i+1]) / 2;
        hc->syms[i] = (huff_codeword_t*)ckd_calloc(hc->numl[i], sizeof(**hc->syms));
    }
    memcpy(nextcode, hc->firstcode, (hc->maxbits + 1) * sizeof(*nextcode));
    /* Traverse the tree again to produce the codebook itself. */
    hc->codewords = hash_table_new(ncw, HASH_CASE_YES);
    agenda = glist_add_ptr(0, root);
    while (agenda) {
        huff_node_t *node = (huff_node_t*)gnode_ptr(agenda);
        agenda = gnode_free(agenda, 0);
        if (node->l) {
            agenda = glist_add_ptr(agenda, node->l);
            agenda = glist_add_ptr(agenda, node->r.r);
        }
        else {
            /* Initialize codebook entry, which also retains symbol pointer. */
            huff_codeword_t *cw;
            uint32 codeword = nextcode[node->nbits] & ((1 << node->nbits) - 1);
            cw = hc->syms[node->nbits] + (codeword - hc->firstcode[node->nbits]);
            cw->nbits = node->nbits;
            cw->r.sval = node->r.sval; /* Will copy ints too... */
            cw->codeword = codeword;
            if (hc->type == HUFF_CODE_INT) {
                hash_table_enter_bkey(hc->codewords,
                                      (char const *)&cw->r.ival,
                                      sizeof(cw->r.ival),
                                      (void *)cw);
            }
            else {
                hash_table_enter(hc->codewords, cw->r.sval, (void *)cw);
            }
            ++nextcode[node->nbits];
        }
    }
    ckd_free(nextcode);
}
Пример #4
0
void fsg_history_entry_add (fsg_history_t *h,
			    word_fsglink_t *link,
			    int32 frame, int32 score, int32 pred,
			    int32 lc, fsg_pnode_ctxt_t rc)
{
  fsg_hist_entry_t *entry, *new_entry;
  int32 s;
  gnode_t *gn, *prev_gn;
  
  /* Skip the optimization for the initial dummy entries; always enter them */
  if (frame < 0) {
    new_entry = (fsg_hist_entry_t *) ckd_calloc(1, sizeof(fsg_hist_entry_t));
    new_entry->fsglink = link;
    new_entry->frame = frame;
    new_entry->score = score;
    new_entry->pred = pred;
    new_entry->lc = lc;
    new_entry->rc = rc;
    
    blkarray_list_append(h->entries, (void *)new_entry);
    return;
  }
  
  s = word_fsglink_to_state(link);
  
  /* Locate where this entry should be inserted in frame_entries[s][lc] */
  prev_gn = NULL;
  for (gn = h->frame_entries[s][lc]; gn; gn = gnode_next(gn)) {
    entry = (fsg_hist_entry_t *) gnode_ptr(gn);
    
    if (entry->score < score)
      break;	/* Found where to insert new entry */
    
    /* Existing entry score not worse than new score */
    if (fsg_pnode_ctxt_sub(&rc, &(entry->rc)) == 0)
      return;	/* rc set reduced to 0; new entry can be ignored */
    
    prev_gn = gn;
  }
  
  /* Create new entry after prev_gn (if prev_gn is NULL, at head) */
  new_entry = (fsg_hist_entry_t *) ckd_calloc(1, sizeof(fsg_hist_entry_t));
  new_entry->fsglink = link;
  new_entry->frame = frame;
  new_entry->score = score;
  new_entry->pred = pred;
  new_entry->lc = lc;
  new_entry->rc = rc;	/* Note: rc set must be non-empty at this point */
  
  if (! prev_gn) {
    h->frame_entries[s][lc] = glist_add_ptr (h->frame_entries[s][lc],
					     (void *) new_entry);
    prev_gn = h->frame_entries[s][lc];
  } else
    prev_gn = glist_insert_ptr (prev_gn, (void *) new_entry);
  
  /*
   * Update the rc set of all the remaining entries in the list.  At this
   * point, gn is the entry, if any, immediately following new entry.
   */
  while (gn) {
    entry = (fsg_hist_entry_t *) gnode_ptr(gn);
    
    if (fsg_pnode_ctxt_sub(&(entry->rc), &rc) == 0) {
      /* rc set of entry reduced to 0; can prune this entry */
      ckd_free ((void *)entry);
      gn = gnode_free (gn, prev_gn);
    } else {
      prev_gn = gn;
      gn = gnode_next(gn);
    }
  }
}