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; }
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; }
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); }
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); } } }