1b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/*
2b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
3b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
4b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Licensed under the Apache License, Version 2.0 (the "License");
5b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * you may not use this file except in compliance with the License.
6b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * You may obtain a copy of the License at
7b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
8b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *     http://www.apache.org/licenses/LICENSE-2.0
9b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
10b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Unless required by applicable law or agreed to in writing, software
11b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * distributed under the License is distributed on an "AS IS" BASIS,
12b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * See the License for the specific language governing permissions and
14b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * limitations under the License.
15b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen */
16b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/**
17b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @file picotrns.c
18b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
19b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * fst processing
20b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
21b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
22b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * All rights reserved.
23b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
24b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * History:
25b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * - 2009-04-20 -- initial version
26b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
27b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen */
28b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
29b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include "picoos.h"
30b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include "picodbg.h"
31b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* #include "picodata.h" */
32b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* #include "picoknow.h" */
33b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include "picoktab.h"
34b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include "picokfst.h"
35b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include "picotrns.h"
36b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
37b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#ifdef __cplusplus
38b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenextern "C" {
39b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
40b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#if 0
41b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
42b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
43b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
44b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
45b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
46b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenpicoos_uint8 picotrns_unplane(picoos_int16 symIn, picoos_uint8 * plane) {
47b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (symIn < 0) {
48b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        (*plane) = 0;
49b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return (picoos_uint8) symIn;
50b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    } else {
51b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        (*plane) = symIn >> 8;
52b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return (picoos_uint8) (symIn & 0xFF);
53b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
54b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
55b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
56b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#if defined(PICO_DEBUG)
57b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
58b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid PICOTRNS_PRINTSYM1(picoknow_KnowledgeBase kbdbg, picoos_int16 insym, picoos_uint8 phonemic)
59b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
60b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include "picokdbg.h"
61b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_int16 sym;
62b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint8 plane;
63b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picokdbg_Dbg dbg = (NULL == kbdbg) ? NULL :  picokdbg_getDbg(kbdbg);
64b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    sym = picotrns_unplane(insym, &plane);
65b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    switch (plane) {
66b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case PICOKFST_PLANE_PHONEMES: /* phones */
67b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if ((NULL == dbg) || !phonemic) {
68b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_INFO_MSG((" %c", sym));
69b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            } else {
70b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_INFO_MSG((" %s", picokdbg_getPhoneSym(dbg, (picoos_uint8) sym)));
71b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
72b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
73b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case PICOKFST_PLANE_ACCENTS: /* accents */
74b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            PICODBG_INFO_MSG((" {A%c}", sym));
75b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
76b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case PICOKFST_PLANE_XSAMPA: /* xsampa symbols */
77b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            PICODBG_INFO_MSG((" {XS:(%i)}", sym));
78b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
79b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case PICOKFST_PLANE_POS: /* part of speech */
80b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            PICODBG_INFO_MSG((" {P:%d}", sym));
81b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
82b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case PICOKFST_PLANE_PB_STRENGTHS: /* phrases */
83b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if (sym == 48) {
84b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_INFO_MSG((" {WB}", sym));
85b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            } else if (sym == 115) {
86b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_INFO_MSG((" {P0}", sym));
87b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            } else {
88b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_INFO_MSG((" {P%c}", sym));
89b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
90b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
91b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case PICOKFST_PLANE_INTERN: /* intern */
92b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            PICODBG_INFO_MSG((" [%c]", sym));
93b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
94b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
95b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
96b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
97b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid PICOTRNS_PRINTSYM(picoknow_KnowledgeBase kbdbg, picoos_int16 insym)
98b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
99b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICOTRNS_PRINTSYM1(kbdbg,insym,1);
100b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
101b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
102b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid PICOTRNS_PRINTSYMSEQ1(picoknow_KnowledgeBase kbdbg, const picotrns_possym_t seq[], const picoos_uint16 seqLen,
103b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                           picoos_uint8 phonemic) {
104b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint16 i;
105b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    for (i=0; i<seqLen; i++) {
106b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        PICOTRNS_PRINTSYM1(kbdbg, seq[i].sym, phonemic);
107b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
108b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
109b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
110b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid PICOTRNS_PRINTSYMSEQ(picoknow_KnowledgeBase kbdbg, const picotrns_possym_t seq[], const picoos_uint16 seqLen) {
111b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICOTRNS_PRINTSYMSEQ1(kbdbg,seq, seqLen, 1);
112b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
113b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
114b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picotrns_printSolution(const picotrns_possym_t outSeq[], const picoos_uint16 outSeqLen)
115b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
116b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_INFO_CTX();
117b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_INFO_MSG(("solution: "));
118b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        PICOTRNS_PRINTSYMSEQ(NULL, outSeq, outSeqLen);
119b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_INFO_MSG(("\n"));
120b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
121b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
122b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picotrns_printSolutionAscii(const picotrns_possym_t outSeq[], const picoos_uint16 outSeqLen)
123b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
124b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_INFO_CTX();
125b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_INFO_MSG(("solution: "));
126b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        PICOTRNS_PRINTSYMSEQ1(NULL, outSeq, outSeqLen,0);
127b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_INFO_MSG(("\n"));
128b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
129b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
130b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
131b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
132b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
133b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
134b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
135b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* * +CT+ ***/
136b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstruct picotrns_transductionState {
137b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint16 phase;   /* transduction phase:
138b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                              0 = before start
139b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                              1 = before regular recursion step
140b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                              2 = before finish
141b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                              3 = after finish */
142b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint32 nrSol;   /* nr of solutions so far */
143b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_int16  recPos;  /* recursion position; must be signed! */
144b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen};
145b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
146b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chentypedef struct picotrns_altDesc {
147b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picokfst_state_t startFSTState;   /**< starting FST state in current recursion position */
148b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_int32     inPos;           /**< corresponding position in input string */
149b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picokfst_state_t altState;        /**< state of alternatives search;
150b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                         - 0 = before pair search
151b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                         - 1 = search state is a valid pair search state
152b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                         - 2 = before inEps search
153b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                         - 3 = search state is a valid inEps trans search state
154b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                         - 4 = no more alternatives */
155b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_int32     searchState;     /**< pair search state or inEps trans search state */
156b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picokfst_symid_t altOutSym;       /**< current output symbol at this recursion position */
157b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_int32     altOutRefPos;    /**< output reference position at this recursion position */
158b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen} picotrns_altDesc_t;
159b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
160b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
161b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenpicotrns_AltDesc picotrns_allocate_alt_desc_buf(picoos_MemoryManager mm, picoos_uint32 maxByteSize, picoos_uint16 * numAltDescs)
162b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
163b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picotrns_AltDesc buf;
164b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    (*numAltDescs) = (picoos_uint32) (maxByteSize / sizeof(picotrns_altDesc_t));
165b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    buf =  (picotrns_AltDesc) picoos_allocate(mm, (*numAltDescs) * sizeof(picotrns_altDesc_t));
166b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (NULL == buf) {
167b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        (*numAltDescs) = 0;
168b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return NULL;
169b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    } else {
170b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return buf;
171b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
172b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
173b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
174b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen void picotrns_deallocate_alt_desc_buf(picoos_MemoryManager mm, picotrns_AltDesc * altDescBuf)
175b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
176b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_deallocate(mm, (void *) altDescBuf);
177b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
178b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
179b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* copy elements from inSeq to outSeq, ignoring elements with epsilon symbol */
180b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenpico_status_t picotrns_eliminate_epsilons(const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen,
181b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen)
182b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
183b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint16 i, j = 0;
184b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
185b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    for (i=0; i < inSeqLen; i++) {
186b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        /* it is assumed that PICOKFST_SYMID_EPS is a hardwired value and not shifted */
187b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (PICOKFST_SYMID_EPS != inSeq[i].sym) {
188b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if (j < maxOutSeqLen) {
189b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                outSeq[j].pos = inSeq[i].pos;
190b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                outSeq[j].sym = inSeq[i].sym;
191b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                j++;
192b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
193b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
194b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        *outSeqLen = j;
195b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
196b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return PICO_OK;
197b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
198b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
199b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
200b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic void insertSym(picotrns_possym_t inSeq[], picoos_uint16 pos, picoos_int16 sym) {
201b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    inSeq[pos].sym = sym;
202b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    inSeq[pos].pos = PICOTRNS_POS_INSERT;
203b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
204b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
205b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* copy elements from inSeq to outSeq, inserting syllable separators in some trivial way.
206b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * inSeq is assumed to be at most PICOTRNS_MAX_NUM_POSSYM, outSeq at least of size PICOTRNS_MAX_NUM_POSSYM  */
207b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenpico_status_t picotrns_trivial_syllabify(picoktab_Phones phones,
208b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        const picotrns_possym_t inSeq[], const picoos_uint16 inSeqLen,
209b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen)
210b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
211b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint16 i = 0, j = 0, out = 0, numInserted = 0;
212b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint8 vowelFound = FALSE;
213b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint16 accentpos = 0;
214b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_int16 accent = 0;
215b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
216b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_TRACE(("start"));
217b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
218b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
219b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    while (i < inSeqLen) {
220b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        /* make sure that at least one more sylSep can be inserted */
221b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (inSeqLen+numInserted+1 >= maxOutSeqLen) {
222b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return PICO_EXC_BUF_OVERFLOW;
223b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
224b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen       /* let j skip consonant cluster */
225b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        accent = 0;
226b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        accentpos = 0;
227b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        while ((j < inSeqLen) && !picoktab_isSyllCarrier(phones,(picoos_uint8)inSeq[j].sym)) {
228b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if ((inSeq[j].sym == picoktab_getPrimstressID(phones))
229b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    || (inSeq[j].sym == picoktab_getPrimstressID(phones))) {
230b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_TRACE(("j skipping stress symbol inSeq[%i].sym = %c", j, inSeq[j].sym));
231b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                accent = inSeq[j].sym;
232b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                accentpos = j;
233b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            } else {
234b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_TRACE(("j skipping consonant inSeq[%i].sym = %c", j, inSeq[j].sym));
235b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
236b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            j++;
237b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
238b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (j < inSeqLen) { /* j is at the start of a new vowel */
239b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            /* copy consonant cluster (moving i) to output, insert syll separator if between vowels */
240b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            while (i < j-1) {
241b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                if ((accent > 0) && (i == accentpos)) {
242b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    PICODBG_TRACE(("skipping inSeq[%i].sym = %c (stress)", i, inSeq[i].sym));
243b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                  i++;
244b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                } else {
245b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_TRACE(("copying inSeq[%i].sym = %c (consonant) into output buffer", i, inSeq[i].sym));
246b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                 outSeq[out++] = inSeq[i++];
247b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                }
248b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
249b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if (vowelFound) { /* we're between vowels */
250b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_TRACE(("inserting syllable separator into output buffer"));
251b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                insertSym(outSeq,out++,picoktab_getSyllboundID(phones));
252b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                if (accent > 0) {
253b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    insertSym(outSeq,out++,accent);
254b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                }
255b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                numInserted++;
256b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
257b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if ((accent > 0) && (i == accentpos)) {
258b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_TRACE(("skipping inSeq[%i].sym = %c (stress)", i, inSeq[i].sym));
259b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen              i++;
260b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            } else {
261b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            PICODBG_TRACE(("copying inSeq[%i].sym = %c (consonant) into output buffer", i, inSeq[i].sym));
262b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen             outSeq[out++] = inSeq[i++];
263b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
264b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            vowelFound = TRUE;
265b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            /* now copy vowel cluster */
266b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            while ((i < inSeqLen) && picoktab_isSyllCarrier(phones,(picoos_uint8)inSeq[i].sym)) {
267b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_TRACE(("copying inSeq[%i].sym = %c (vowel) into output buffer", i, inSeq[i].sym));
268b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                outSeq[out++] = inSeq[i++];
269b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
270b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            j = i;
271b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        } else { /* j is at end of word or end of input */
272b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            while (i < j) {
273b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_TRACE(("copying inSeq[%i].sym = %c (consonant or stress) into output buffer", i, inSeq[i].sym));
274b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                outSeq[out++] = inSeq[i++];
275b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
276b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
277b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        *outSeqLen = out;
278b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
279b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_ASSERT((out == inSeqLen + numInserted));
280b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
281b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return PICO_OK;
282b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
283b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
284b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
285b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* ******** +CT+: full transduction procedure **********/
286b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
287b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
288b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Gets next acceptable alternative for output symbol '*outSym' at current recursion position
289b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   starting from previous alternative in 'altDesc'; possibly uses input symbol
290b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   given by 'inSeq'/'inSeq'; returns whether alterative was found in '*found';
291b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   if '*found', the other output values ('*outRefPos', '*endFSTstate', '*nextInPos'*)
292b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   return the characteristics for next recursion step;
293b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   if '*found' is false, the output values are undefined. */
294b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
295b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic void GetNextAlternative (picokfst_FST fst, picotrns_AltDesc altDesc,
296b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen,
297b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                picokfst_symid_t * outSym, picoos_int32 * outRefPos,
298b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                picokfst_state_t * endFSTState, picoos_int32 * nextInPos, picoos_bool * found)
299b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
300b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
301b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_bool inSymFound;
302b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_bool pairFound;
303b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picokfst_class_t pairClass;
304b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_bool inEpsTransFound;
305b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picokfst_symid_t inSym;
306b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
307b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    (*found) = 0;
308b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    do {
309b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        switch (altDesc->altState) {
310b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            case 0:   /* before pair search */
311b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                if (altDesc->inPos < inSeqLen) {
312b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    inSym = inSeq[altDesc->inPos].sym;
313b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    if (inSym == PICOKFST_SYMID_EPS) {
314b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        /* very special case: input epsilon simply produces eps in output
315b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                           without fst state change */
316b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        (*found) = 1;
317b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        (*outSym) = PICOKFST_SYMID_EPS;
318b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        (*outRefPos) = inSeq[altDesc->inPos].pos;
319b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        (*endFSTState) = altDesc->startFSTState;
320b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        (*nextInPos) = altDesc->inPos + 1;
321b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        altDesc->altState = 2;
322b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    } else {
323b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        /* start search for alternatives using input symbol */
324b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        picokfst_kfstStartPairSearch(fst,inSeq[altDesc->inPos].sym,& inSymFound,& altDesc->searchState);
325b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        if (!inSymFound) {
326b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                            altDesc->altState = 2;
327b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                            PICODBG_INFO_CTX();
328b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                            PICODBG_INFO_MSG((" didnt find symbol "));
329b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                            PICOTRNS_PRINTSYM(NULL, inSeq[altDesc->inPos].sym);
330b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                            PICODBG_INFO_MSG(("\n"));
331b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
332b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        } else {
333b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                            altDesc->altState = 1;
334b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        }
335b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    }
336b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                } else {
337b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    altDesc->altState = 2;
338b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                }
339b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                break;
340b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            case 1:   /* within pair search */
341b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                picokfst_kfstGetNextPair(fst,& altDesc->searchState,& pairFound,& (*outSym),& pairClass);
342b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                if (pairFound) {
343b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    picokfst_kfstGetTrans(fst,altDesc->startFSTState,pairClass,& (*endFSTState));
344b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    if ((*endFSTState) > 0) {
345b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        (*found) = 1;
346b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        (*outRefPos) = inSeq[altDesc->inPos].pos;
347b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        (*nextInPos) = altDesc->inPos + 1;
348b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    }
349b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                } else {
350b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    /* no more pair found */
351b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    altDesc->altState = 2;
352b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                }
353b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                break;
354b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            case 2:   /* before inEps trans search */
355b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                picokfst_kfstStartInEpsTransSearch(fst,altDesc->startFSTState,& inEpsTransFound,& altDesc->searchState);
356b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                if (inEpsTransFound) {
357b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    altDesc->altState = 3;
358b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                } else {
359b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    altDesc->altState = 4;
360b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                }
361b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                break;
362b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            case 3:   /* within inEps trans search */
363b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                picokfst_kfstGetNextInEpsTrans(fst,& altDesc->searchState,& inEpsTransFound,& (*outSym),& (*endFSTState));
364b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                if (inEpsTransFound) {
365b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    (*found) = 1;
366b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    (*outRefPos) =  PICOTRNS_POS_INSERT;
367b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    (*nextInPos) = altDesc->inPos;
368b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                } else {
369b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    altDesc->altState = 4;
370b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                }
371b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                break;
372b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            case 4:   /* no more alternatives */
373b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                break;
374b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
375b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    } while (! ((*found) || (altDesc->altState == 4)) );  /* i.e., until (*found) || (altState == 4) */
376b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
377b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
378b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
379b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
380b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Transfers current alternatives path stored in 'altDesc' with current path length 'pathLen'
381b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   into 'outSeq'/'outSeqLen'. The number of solutions is incremented. */
382b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
383b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic void NoteSolution (picoos_uint32 * nrSol, picotrns_printSolutionFct printSolution,
384b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                          picotrns_altDesc_t altDesc[], picoos_uint16 pathLen,
385b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                          picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen)
386b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
387b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    register picotrns_AltDesc ap;
388b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint32 i;
389b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
390b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    (*nrSol)++;
391b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    (*outSeqLen) = 0;
392b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    for (i = 0; i < pathLen; i++) {
393b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (i < maxOutSeqLen) {
394b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            ap = &altDesc[i];
395b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            outSeq[i].sym = ap->altOutSym;
396b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            outSeq[i].pos = ap->altOutRefPos;
397b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            (*outSeqLen)++;
398b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
399b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
400b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (pathLen > maxOutSeqLen) {
401b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        PICODBG_WARN(("**** output symbol array too small to hold full solution\n"));
402b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
403b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (printSolution != NULL) {
404b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        printSolution(outSeq,(*outSeqLen));
405b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
406b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
407b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
408b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
409b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
410b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* *
411b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    general scheme to get all solutions ("position" refers to abstract backtracking recursion depth,
412b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    which in the current solution is equal to the output symbol position):
413b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
414b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    "set position to first position";
415b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    "initialize alternatives in first position";
416b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    REPEAT
417b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen      IF "current state in current position is a solution" THEN
418b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        "note solution";
419b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen      END;
420b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen      "get first or next acceptable alternative in current position";
421b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen      IF "acceptable alternative found" THEN
422b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        "note alternative";
423b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        "go to next position";
424b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        "initialize alternatives in that position";
425b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen      ELSE
426b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        "step back to previous position";
427b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen      END;
428b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    UNTIL "current position is before first position"
429b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen***/
430b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
431b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
432b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Initializes transduction state for further use in repeated application
433b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   of 'TransductionStep'. */
434b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
435b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic void StartTransduction (struct picotrns_transductionState * transductionState)
436b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
437b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    (*transductionState).phase = 0;
438b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
439b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
440b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
441b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
442b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Performs one step in the transduction of 'inSeqLen' input symbols with corresponding
443b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   reference positions in 'inSeq'. '*transductionState' must have been
444b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   initialized by 'StartTransduction'. Repeat calls to this procedure until '*finished' returns true.
445b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   The output is returned in 'outSeqLen' symbols and reference positions in 'outSeq'.
446b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   The output reference positions refer to the corresponding input reference positions.
447b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   Inserted output symbols receive the reference position -1. If several solutions are possible,
448b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   only the last found solution is returned.
449b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   'altDesc' is a temporary workspace which should be at least one cell longer than 'outSeq'.
450b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   'firstSolOnly' determines whether only the first solution should be found or if
451b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   the search should go on to find all solutions (mainly for testing purposes).
452b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
453b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   NOTE: current version written for use in single repetitive steps;
454b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   could be simplified if full transduction can be done as an atomic operation */
455b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
456b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic void TransductionStep (picokfst_FST fst, struct picotrns_transductionState * transductionState,
457b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                              picotrns_altDesc_t altDesc[], picoos_uint16 maxAltDescLen,
458b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                              picoos_bool firstSolOnly, picotrns_printSolutionFct printSolution,
459b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                              const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen,
460b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                              picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen,
461b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                              picoos_bool * finished)
462b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
463b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    register picotrns_AltDesc ap;
464b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_int32 i;
465b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picokfst_state_t endFSTState;
466b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_int32 nextInPos;
467b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_bool found;
468b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picokfst_symid_t outSym;
469b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_int32 outRefPos;
470b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_int32 tmpRecPos;
471b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
472b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    (*finished) = 0;
473b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    tmpRecPos = (*transductionState).recPos;
474b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    switch ((*transductionState).phase) {
475b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case 0:   /* before initialization */
476b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            (*transductionState).nrSol = 0;
477b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
478b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            /* check for initial solution (empty strings are always accepted) */
479b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if (inSeqLen == 0) {
480b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                NoteSolution(& (*transductionState).nrSol,printSolution,altDesc,0,outSeq,outSeqLen,maxOutSeqLen);
481b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
482b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
483b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            /* initialize first recursion position */
484b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            tmpRecPos = 0;
485b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            ap = & altDesc[0];
486b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            ap->startFSTState = 1;
487b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            ap->inPos = 0;
488b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            ap->altState = 0;
489b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            (*transductionState).phase = 1;
490b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
491b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
492b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case 1:   /* before regular recursion step */
493b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if ((tmpRecPos < 0) || (firstSolOnly && ((*transductionState).nrSol > 0))) {
494b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                /* end reached */
495b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                (*transductionState).phase = 2;
496b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            } else {
497b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                /* not finished; do regular step */
498b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
499b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                /* get first or next acceptable alternative in current position */
500b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                GetNextAlternative(fst,& altDesc[tmpRecPos],inSeq,inSeqLen,& outSym,& outRefPos,& endFSTState,& nextInPos,& found);
501b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                if (found) {
502b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    /* note alternative in current position */
503b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    ap = & altDesc[tmpRecPos];
504b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    ap->altOutSym = outSym;
505b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    ap->altOutRefPos = outRefPos;
506b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
507b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    /* check for solution after found alternative */
508b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    if ((nextInPos == inSeqLen) && picokfst_kfstIsAcceptingState(fst,endFSTState)) {
509b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        NoteSolution(& (*transductionState).nrSol,printSolution,altDesc,tmpRecPos+1,
510b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                     outSeq,outSeqLen,maxOutSeqLen);
511b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    }
512b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
513b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    /* go to next position if possible, start search for follower alternative symbols */
514b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    if (tmpRecPos < maxAltDescLen-1) {
515b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        /* got to next position */
516b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        tmpRecPos = tmpRecPos + 1;
517b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
518b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        /* initialize alternatives in new position */
519b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        ap = & altDesc[tmpRecPos];
520b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        ap->startFSTState = endFSTState;
521b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        ap->inPos = nextInPos;
522b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        ap->altState = 0;
523b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
524b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    } else {
525b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        /* do not go on due to limited path but still treat alternatives in current position */
526b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        PICODBG_WARN(("--- transduction path too long; may fail to find solution\n"));
527b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    }
528b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                } else {  /* no more acceptable alternative found in current position */
529b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    /* backtrack to previous recursion */
530b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    tmpRecPos = tmpRecPos - 1;
531b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                }
532b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
533b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
534b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
535b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case 2:   /* before finish */
536b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if ((*transductionState).nrSol == 0) {
537b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_WARN(("--- no transduction solution found, using input as output\n"));
538b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                i = 0;
539b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                while ((i < inSeqLen) && (i < maxOutSeqLen)) {
540b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    outSeq[i].sym = inSeq[i].sym;
541b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    outSeq[i].pos = inSeq[i].pos;
542b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    i++;
543b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                }
544b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                (*outSeqLen) = i;
545b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            } else if ((*transductionState).nrSol > 1) {
546b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                PICODBG_WARN(("--- more than one transducer solutions found\n"));
547b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
548b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            (*transductionState).phase = 3;
549b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
550b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
551b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case 3:   /* after finish */
552b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            (*finished) = 1;
553b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
554b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
555b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    (*transductionState).recPos = tmpRecPos;
556b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
557b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
558b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
559b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
560b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* see description in header */
561b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenpico_status_t picotrns_transduce (picokfst_FST fst, picoos_bool firstSolOnly,
562b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                         picotrns_printSolutionFct printSolution,
563b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                         const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen,
564b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                         picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen,
565b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                         picotrns_AltDesc altDescBuf, picoos_uint16 maxAltDescLen,
566b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                         picoos_uint32 *nrSteps)
567b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
568b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    struct picotrns_transductionState transductionState;
569b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_bool finished;
570b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
571b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#if defined(PICO_DEBUG)
572b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
573b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoos_uint16 i;
574b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
575b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        PICODBG_INFO_CTX();
576b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        PICODBG_INFO_MSG(("got input: "));
577b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        for (i=0; i<inSeqLen; i++) {
578b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            PICODBG_INFO_MSG((" %d", inSeq[i].sym));
579b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
580b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        PICODBG_INFO_MSG((" ("));
581b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        PICOTRNS_PRINTSYMSEQ(NULL,inSeq,inSeqLen);
582b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        PICODBG_INFO_MSG((")\n"));
583b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
584b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
585b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   StartTransduction(&transductionState);
586b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    finished = 0;
587b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    *nrSteps = 0;
588b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    while (!finished) {
589b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        TransductionStep(fst,&transductionState,altDescBuf,maxAltDescLen,firstSolOnly,printSolution,
590b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                         inSeq,inSeqLen,outSeq,outSeqLen,maxOutSeqLen,&finished);
591b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        (*nrSteps)++;
592b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
593b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
594b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return PICO_OK;
595b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
596b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
597b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
598b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/**
599b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Data structure for picotrns_SimpleTransducer object.
600b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen */
601b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chentypedef struct picotrns_simple_transducer {
602b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_Common common;
603b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picotrns_possym_t possymBufA[PICOTRNS_MAX_NUM_POSSYM+1];
604b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picotrns_possym_t possymBufB[PICOTRNS_MAX_NUM_POSSYM+1];
605b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picotrns_possym_t * possymBuf; /**< the buffer of the pos/sym pairs */
606b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picotrns_possym_t * possymBufTmp;
607b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint16 possymReadPos, possymWritePos; /* next pos to read from phonBufIn, next pos to write to phonBufIn */
608b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
609b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    /* buffer for internal calculation of transducer */
610b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picotrns_AltDesc altDescBuf;
611b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    /* the number of AltDesc in the buffer */
612b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint16 maxAltDescLen;
613b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen} picotrns_simple_transducer_t;
614b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
615b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
616b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenpico_status_t  picotrns_stInitialize(picotrns_SimpleTransducer transducer)
617b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
618b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    transducer->possymBuf = transducer->possymBufA;
619b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    transducer->possymBufTmp = transducer->possymBufB;
620b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    transducer->possymReadPos = 0;
621b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    transducer->possymWritePos = 0;
622b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return PICO_OK;
623b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
624b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** creates a SimpleTranducer with a working buffer of given size
625b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
626b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @param mm      MemoryManager handle
627b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @param common  Common handle
628b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @param maxAltDescLen maximal size for working buffer (in bytes)
629b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @return handle to new SimpleTransducer or NULL if error
630b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen */
631b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenpicotrns_SimpleTransducer picotrns_newSimpleTransducer(picoos_MemoryManager mm,
632b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                              picoos_Common common,
633b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                              picoos_uint16 maxAltDescLen)
634b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
635b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picotrns_SimpleTransducer this;
636b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    this = picoos_allocate(mm, sizeof(picotrns_simple_transducer_t));
637b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (this == NULL) {
638b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoos_deallocate(mm, (void *)&this);
639b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL);
640b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return NULL;
641b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
642b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
643b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    /* allocate working buffer */
644b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    this->altDescBuf = picotrns_allocate_alt_desc_buf(mm, maxAltDescLen, &this->maxAltDescLen);
645b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (this->altDescBuf == NULL) {
646b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoos_deallocate(mm, (void *)&this);
647b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL);
648b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return NULL;
649b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
650b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    this->common = common;
651b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picotrns_stInitialize(this);
652b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return this;
653b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
654b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** disposes a SimpleTransducer
655b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
656b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @param this
657b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @param mm
658b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @return PICO_OK
659b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen */
660b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenpico_status_t picotrns_disposeSimpleTransducer(picotrns_SimpleTransducer * this,
661b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                        picoos_MemoryManager mm)
662b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
663b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (NULL != (*this)) {
664b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picotrns_deallocate_alt_desc_buf(mm,&(*this)->altDescBuf);
665b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoos_deallocate(mm, (void *) this);
666b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        (*this) = NULL;
667b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
668b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return PICO_OK;
669b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
670b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
671b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** transduces the contents previously inserted via @ref picotrns_newSimpleTransducer and @ref
672b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  picotrns_disposeSimpleTransducer.
673b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
674b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @param this
675b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @param fst
676b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @return
677b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen */
678b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenpico_status_t picotrns_stTransduce(picotrns_SimpleTransducer this, picokfst_FST fst)
679b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
680b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint16 outSeqLen;
681b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint32 nrSteps;
682b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    pico_status_t status;
683b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
684b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    status = picotrns_transduce(fst,TRUE,NULL,
685b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            this->possymBuf, this->possymWritePos,
686b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            this->possymBufTmp,&outSeqLen, PICOTRNS_MAX_NUM_POSSYM,
687b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            this->altDescBuf,this->maxAltDescLen,&nrSteps);
688b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK != status) {
689b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return status;
690b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
691b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return picotrns_eliminate_epsilons(this->possymBufTmp,outSeqLen,this->possymBuf,&this->possymWritePos,PICOTRNS_MAX_NUM_POSSYM);
692b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
693b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
694b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/**
695b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Add chars from NULLC-terminated string \c inStr, shifted to plane \c plane, to internal input buffer of
696b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  \c transducer.
697b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
698b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @param this is an initialized picotrns_SimpleTransducer
699b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @param inStr NULLC-terminated byte sequence
700b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @param plane
701b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @return PICO_OK, if all bytes fit into buffer, or PICO_EXC_BUF_OVERFLOW otherwise
702b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen */
703b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenpico_status_t picotrns_stAddWithPlane(picotrns_SimpleTransducer this, picoos_char * inStr, picoos_uint8 plane)
704b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
705b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    while ((*inStr) && (this->possymWritePos < PICOTRNS_MAX_NUM_POSSYM)) {
706b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        this->possymBuf[this->possymWritePos].pos = PICOTRNS_POS_INSERT;
707b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        this->possymBuf[this->possymWritePos].sym = (plane << 8) + (*inStr);
708b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        PICODBG_DEBUG(("inserting pos/sym = %i/'%c' at pos %i",
709b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                this->possymBuf[this->possymWritePos].pos,
710b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                this->possymBuf[this->possymWritePos].sym,
711b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                this->possymWritePos));
712b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        this->possymWritePos++;
713b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        inStr++;
714b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
715b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (!(*inStr)) {
716b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return PICO_OK;
717b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    } else {
718b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return PICO_EXC_BUF_OVERFLOW;
719b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
720b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
721b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
722b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenpico_status_t picotrns_stGetSymSequence(
723b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picotrns_SimpleTransducer this,
724b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoos_uint8 * outputSymIds,
725b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoos_uint32 maxOutputSymIds)
726b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
727b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint8 plane;
728b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoos_uint32 outputCount = 0;
729b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    while ((this->possymReadPos < this->possymWritePos) && (outputCount < maxOutputSymIds)) {
730b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        *outputSymIds++ = picotrns_unplane(this->possymBuf[this->possymReadPos++].sym, &plane);
731b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        outputCount++;
732b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
733b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    *outputSymIds = NULLC;
734b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (outputCount <= maxOutputSymIds) {
735b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return PICO_OK;
736b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    } else {
737b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return PICO_EXC_BUF_OVERFLOW;
738b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
739b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
740b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
741b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#ifdef __cplusplus
742b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
743b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
744b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
745b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* end picotrns.c */
746