14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// map.h
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Licensed under the Apache License, Version 2.0 (the "License");
44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// you may not use this file except in compliance with the License.
54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// You may obtain a copy of the License at
64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//      http://www.apache.org/licenses/LICENSE-2.0
84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Unless required by applicable law or agreed to in writing, software
104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// distributed under the License is distributed on an "AS IS" BASIS,
114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// See the License for the specific language governing permissions and
134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// limitations under the License.
144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// \file
174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Class to map over/transform arcs e.g., change semirings or
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// implement project/invert.
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifndef FST_LIB_MAP_H__
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define FST_LIB_MAP_H__
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/cache.h"
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/mutable-fst.h"
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectnamespace fst {
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// This determines how final weights are mapped.
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectenum MapFinalAction {
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // A final weight is mapped into a final weight. An error
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // is raised if this is not possible.
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MAP_NO_SUPERFINAL,
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // A final weight is mapped to an arc to the superfinal state
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // when the result cannot be represented as a final weight.
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // The superfinal state will be added only if it is needed.
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MAP_ALLOW_SUPERFINAL,
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // A final weight is mapped to an arc to the superfinal state
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // unless the result can be represented as a final weight of weight
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Zero(). The superfinal state is always added (if the input is
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // not the empty Fst).
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MAP_REQUIRE_SUPERFINAL
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper Interface - class determinies how arcs and final weights
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// are mapped.
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// class Mapper {
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//  public:
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//   // Maps an arc type A to arc type B.
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//   B operator()(const A &arc);
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//   // Specifies final action the mapper requires (see above).
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//   // The mapper will be passed final weights as arcs of the
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//   // form A(0, 0, weight, kNoStateId).
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//   MapFinalAction FinalAction() const;
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//   // This specifies the known properties of an Fst mapped by this
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//   // mapper. It takes as argument the input Fst's known properties.
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//   uint64 Properties(uint64 props) const;
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// }
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// The Map functions and classes below will use the FinalAction()
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// method of the mapper to determine how to treat final weights,
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// e.g. whether to add a superfinal state. They will use the Properties()
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// method to set the result Fst properties.
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// We include a various map versions below. One dimension of
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// variation is whether the mapping mutates its input, writes to a
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// new result Fst, or is an on-the-fly Fst. Another dimension is how
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// we pass the mapper. We allow passing the mapper by pointer
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// for cases that we need to change the state of the user's mapper.
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// This is the case with the encode mapper, which is reused during
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// decoding. We also include map versions that pass the mapper
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// by value or const reference when this suffices.
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Maps an arc type A using a mapper function object C, passed
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// by pointer.  This version modifies its Fst input.
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate<class A, class C>
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid Map(MutableFst<A> *fst, C* mapper) {
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::StateId StateId;
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::Weight Weight;
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (fst->Start() == kNoStateId)
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return;
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 props = fst->Properties(kFstProperties, false);
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction final_action = mapper->FinalAction();
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId superfinal = kNoStateId;
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (final_action == MAP_REQUIRE_SUPERFINAL) {
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    superfinal = fst->AddState();
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fst->SetFinal(superfinal, Weight::One());
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (StateId s = 0; s < fst->NumStates(); ++s) {
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (MutableArcIterator< MutableFst<A> > aiter(fst, s);
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         !aiter.Done(); aiter.Next()) {
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      const A &arc = aiter.Value();
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      aiter.SetValue((*mapper)(arc));
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    switch (final_action) {
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      case MAP_NO_SUPERFINAL:
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      default: {
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        A final_arc = (*mapper)(A(0, 0, fst->Final(s), kNoStateId));
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        CHECK(final_arc.ilabel == 0 && final_arc.olabel == 0);
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        fst->SetFinal(s, final_arc.weight);
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        break;
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      case MAP_ALLOW_SUPERFINAL: {
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (s != superfinal) {
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          A final_arc = (*mapper)(A(0, 0, fst->Final(s), kNoStateId));
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (final_arc.ilabel != 0 || final_arc.olabel != 0) {
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            // Add a superfinal state if not already done.
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (superfinal == kNoStateId) {
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              superfinal = fst->AddState();
1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              fst->SetFinal(superfinal, Weight::One());
1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            }
1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            final_arc.nextstate = superfinal;
1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            fst->AddArc(s, final_arc);
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            fst->SetFinal(s, Weight::Zero());
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          } else {
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            fst->SetFinal(s, final_arc.weight);
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          break;
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      case MAP_REQUIRE_SUPERFINAL: {
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (s != superfinal) {
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          A final_arc = (*mapper)(A(0, 0, fst->Final(s), kNoStateId));
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (final_arc.ilabel != 0 || final_arc.olabel != 0 ||
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              final_arc.weight != Weight::Zero())
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            fst->AddArc(s, A(final_arc.ilabel, final_arc.olabel,
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                             final_arc.weight, superfinal));
1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            fst->SetFinal(s, Weight::Zero());
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        break;
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fst->SetProperties(mapper->Properties(props), kFstProperties);
1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Maps an arc type A using a mapper function object C, passed
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// by value.  This version modifies its Fst input.
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate<class A, class C>
1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid Map(MutableFst<A> *fst, C mapper) {
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Map(fst, &mapper);
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Maps an arc type A to an arc type B using mapper function
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// object C, passed by pointer. This version writes the mapped
1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// input Fst to an output MutableFst.
1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate<class A, class B, class C>
1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid Map(const Fst<A> &ifst, MutableFst<B> *ofst, C* mapper) {
1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::StateId StateId;
1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::Weight Weight;
1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ofst->DeleteStates();
1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ofst->SetInputSymbols(ifst.InputSymbols());
1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ofst->SetOutputSymbols(ifst.OutputSymbols());
1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (ifst.Start() == kNoStateId)
1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return;
1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Add all states.
1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (StateIterator< Fst<A> > siter(ifst); !siter.Done(); siter.Next())
1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ofst->AddState();
1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction final_action = mapper->FinalAction();
1744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId superfinal = kNoStateId;
1754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (final_action == MAP_REQUIRE_SUPERFINAL) {
1764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    superfinal = ofst->AddState();
1774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ofst->SetFinal(superfinal, B::Weight::One());
1784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (StateIterator< Fst<A> > siter(ifst); !siter.Done(); siter.Next()) {
1804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    StateId s = siter.Value();
1814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (s == ifst.Start())
1824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ofst->SetStart(s);
1834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (ArcIterator< Fst<A> > aiter(ifst, s); !aiter.Done(); aiter.Next())
1854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ofst->AddArc(s, (*mapper)(aiter.Value()));
1864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    switch (final_action) {
1884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      case MAP_NO_SUPERFINAL:
1894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      default: {
1904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        B final_arc = (*mapper)(A(0, 0, ifst.Final(s), kNoStateId));
1914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        CHECK(final_arc.ilabel == 0 && final_arc.olabel == 0);
1924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ofst->SetFinal(s, final_arc.weight);
1934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        break;
1944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
1954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      case MAP_ALLOW_SUPERFINAL: {
1964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        B final_arc = (*mapper)(A(0, 0, ifst.Final(s), kNoStateId));
1974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (final_arc.ilabel != 0 || final_arc.olabel != 0) {
1984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            // Add a superfinal state if not already done.
1994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (superfinal == kNoStateId) {
2004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            superfinal = ofst->AddState();
2014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            ofst->SetFinal(superfinal, B::Weight::One());
2024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
2034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          final_arc.nextstate = superfinal;
2044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ofst->AddArc(s, final_arc);
2054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ofst->SetFinal(s, B::Weight::Zero());
2064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        } else {
2074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ofst->SetFinal(s, final_arc.weight);
2084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
2094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        break;
2104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
2114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      case MAP_REQUIRE_SUPERFINAL: {
2124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        B final_arc = (*mapper)(A(0, 0, ifst.Final(s), kNoStateId));
2134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (final_arc.ilabel != 0 || final_arc.olabel != 0 ||
2144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            final_arc.weight != B::Weight::Zero())
2154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ofst->AddArc(s, B(final_arc.ilabel, final_arc.olabel,
2164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                            final_arc.weight, superfinal));
2174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ofst->SetFinal(s, B::Weight::Zero());
2184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        break;
2194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
2204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 iprops = ifst.Properties(kCopyProperties, false);
2234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 oprops = ofst->Properties(kFstProperties, false);
2244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ofst->SetProperties(mapper->Properties(iprops) | oprops, kFstProperties);
2254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Maps an arc type A to an arc type B using mapper function
2284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// object C, passed by value. This version writes the mapped input
2294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Fst to an output MutableFst.
2304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate<class A, class B, class C>
2314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid Map(const Fst<A> &ifst, MutableFst<B> *ofst, C mapper) {
2324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Map(ifst, ofst, &mapper);
2334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct MapFstOptions : public CacheOptions {
2374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // MapFst default caching behaviour is to do no caching. Most
2384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // mappers are cheap and therefore we save memory by not doing
2394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // caching.
2404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFstOptions() : CacheOptions(true, 0) {}
2414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFstOptions(const CacheOptions& opts) : CacheOptions(opts) {}
2424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
2434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A, class B, class C> class MapFst;
2464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Implementation of delayed MapFst.
2484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A, class B, class C>
2494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass MapFstImpl : public CacheImpl<B> {
2504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project public:
2514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  using FstImpl<B>::SetType;
2524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  using FstImpl<B>::SetProperties;
2534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  using FstImpl<B>::Properties;
2544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  using FstImpl<B>::SetInputSymbols;
2554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  using FstImpl<B>::SetOutputSymbols;
2564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  using VectorFstBaseImpl<typename CacheImpl<B>::State>::NumStates;
2584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  using CacheImpl<B>::HasArcs;
2604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  using CacheImpl<B>::HasFinal;
2614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  using CacheImpl<B>::HasStart;
2624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  friend class StateIterator< MapFst<A, B, C> >;
2644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef B Arc;
2664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename B::Weight Weight;
2674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename B::StateId StateId;
2684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFstImpl(const Fst<A> &fst, const C &mapper,
2704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                 const MapFstOptions& opts)
2714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      : CacheImpl<B>(opts), fst_(fst.Copy()),
2724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        mapper_(new C(mapper)),
2734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        own_mapper_(true),
2744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        superfinal_(kNoStateId),
2754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        nstates_(0) {
2764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    Init();
2774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFstImpl(const Fst<A> &fst, C *mapper,
2804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                 const MapFstOptions& opts)
2814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      : CacheImpl<B>(opts), fst_(fst.Copy()),
2824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        mapper_(mapper),
2834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        own_mapper_(false),
2844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        superfinal_(kNoStateId),
2854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        nstates_(0) {
2864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    Init();
2874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ~MapFstImpl() {
2914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    delete fst_;
2924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (own_mapper_) delete mapper_;
2934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId Start() {
2964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!HasStart())
297ea4ad6085a8661b5513c394316108c0ef26f3e7bAl Sutton      this->SetStart(FindOState(fst_->Start()));
2984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return CacheImpl<B>::Start();
2994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Weight Final(StateId s) {
3024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!HasFinal(s)) {
3034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      switch (final_action_) {
3044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        case MAP_NO_SUPERFINAL:
3054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        default: {
3064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)),
3074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                        kNoStateId));
3084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          CHECK(final_arc.ilabel == 0 && final_arc.olabel == 0);
309ea4ad6085a8661b5513c394316108c0ef26f3e7bAl Sutton          this->SetFinal(s, final_arc.weight);
3104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          break;
3114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
3124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        case MAP_ALLOW_SUPERFINAL: {
3134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (s == superfinal_) {
314ea4ad6085a8661b5513c394316108c0ef26f3e7bAl Sutton            this->SetFinal(s, Weight::One());
3154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          } else {
3164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)),
3174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                          kNoStateId));
3184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (final_arc.ilabel == 0 && final_arc.olabel == 0)
319ea4ad6085a8661b5513c394316108c0ef26f3e7bAl Sutton              this->SetFinal(s, final_arc.weight);
3204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            else
321ea4ad6085a8661b5513c394316108c0ef26f3e7bAl Sutton              this->SetFinal(s, Weight::Zero());
3224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
3234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          break;
3244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
3254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        case MAP_REQUIRE_SUPERFINAL: {
326ea4ad6085a8661b5513c394316108c0ef26f3e7bAl Sutton          this->SetFinal(s, s == superfinal_ ? Weight::One() : Weight::Zero());
3274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          break;
3284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
3294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
3304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return CacheImpl<B>::Final(s);
3324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  size_t NumArcs(StateId s) {
3354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!HasArcs(s))
3364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      Expand(s);
3374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return CacheImpl<B>::NumArcs(s);
3384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  size_t NumInputEpsilons(StateId s) {
3414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!HasArcs(s))
3424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      Expand(s);
3434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return CacheImpl<B>::NumInputEpsilons(s);
3444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  size_t NumOutputEpsilons(StateId s) {
3474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!HasArcs(s))
3484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      Expand(s);
3494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return CacheImpl<B>::NumOutputEpsilons(s);
3504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  void InitArcIterator(StateId s, ArcIteratorData<B> *data) {
3534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!HasArcs(s))
3544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      Expand(s);
3554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    CacheImpl<B>::InitArcIterator(s, data);
3564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  void Expand(StateId s) {
3594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // Add exiting arcs.
360ea4ad6085a8661b5513c394316108c0ef26f3e7bAl Sutton    if (s == superfinal_) { this->SetArcs(s); return; }
3614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (ArcIterator< Fst<A> > aiter(*fst_, FindIState(s));
3634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         !aiter.Done(); aiter.Next()) {
3644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      A aarc(aiter.Value());
3654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      aarc.nextstate = FindOState(aarc.nextstate);
3664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      const B& barc = (*mapper_)(aarc);
367ea4ad6085a8661b5513c394316108c0ef26f3e7bAl Sutton      this->AddArc(s, barc);
3684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // Check for superfinal arcs.
3714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!HasFinal(s) || Final(s) == Weight::Zero())
3724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      switch (final_action_) {
3734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        case MAP_NO_SUPERFINAL:
3744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        default:
3754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          break;
3764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        case MAP_ALLOW_SUPERFINAL: {
3774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)),
3784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                        kNoStateId));
3794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (final_arc.ilabel != 0 || final_arc.olabel != 0) {
3804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (superfinal_ == kNoStateId)
3814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project              superfinal_ = nstates_++;
3824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            final_arc.nextstate = superfinal_;
383ea4ad6085a8661b5513c394316108c0ef26f3e7bAl Sutton            this->AddArc(s, final_arc);
3844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
3854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          break;
3864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
3874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      case MAP_REQUIRE_SUPERFINAL: {
3884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)),
3894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                      kNoStateId));
3904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (final_arc.ilabel != 0 || final_arc.olabel != 0 ||
3914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            final_arc.weight != B::Weight::Zero())
392ea4ad6085a8661b5513c394316108c0ef26f3e7bAl Sutton          this->AddArc(s, B(final_arc.ilabel, final_arc.olabel,
3934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                      final_arc.weight, superfinal_));
3944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        break;
3954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
3964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
397ea4ad6085a8661b5513c394316108c0ef26f3e7bAl Sutton    this->SetArcs(s);
3984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project private:
4014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  void Init() {
4024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SetType("map");
4034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SetInputSymbols(fst_->InputSymbols());
4044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SetOutputSymbols(fst_->OutputSymbols());
4054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (fst_->Start() == kNoStateId) {
4064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      final_action_ = MAP_NO_SUPERFINAL;
4074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      SetProperties(kNullProperties);
4084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    } else {
4094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      final_action_ = mapper_->FinalAction();
4104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      uint64 props = fst_->Properties(kCopyProperties, false);
4114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      SetProperties(mapper_->Properties(props));
4124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (final_action_ == MAP_REQUIRE_SUPERFINAL)
4134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        superfinal_ = 0;
4144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
4154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Maps from output state to input state.
4184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId FindIState(StateId s) {
4194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (superfinal_ == kNoStateId || s < superfinal_)
4204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return s;
4214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else
4224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return s - 1;
4234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Maps from input state to output state.
4264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId FindOState(StateId is) {
4274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    StateId os;
4284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (superfinal_ == kNoStateId || is < superfinal_)
4294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      os = is;
4304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else
4314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      os = is + 1;
4324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (os >= nstates_)
4344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      nstates_ = os + 1;
4354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return os;
4374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  const Fst<A> *fst_;
4414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  C*   mapper_;
4424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bool own_mapper_;
4434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction final_action_;
4444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId superfinal_;
4464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId nstates_;
4474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
4484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Maps an arc type A to an arc type B using Mapper function object
4514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// C. This version is a delayed Fst.
4524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A, class B, class C>
4534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass MapFst : public Fst<B> {
4544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project public:
4554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  friend class ArcIterator< MapFst<A, B, C> >;
4564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  friend class StateIterator< MapFst<A, B, C> >;
4574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  friend class CacheArcIterator< MapFst<A, B, C> >;
4584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef B Arc;
4604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename B::Weight Weight;
4614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename B::StateId StateId;
4624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef CacheState<B> State;
4634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFst(const Fst<A> &fst, const C &mapper,
4654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             const MapFstOptions& opts)
4664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      : impl_(new MapFstImpl<A, B, C>(fst, mapper, opts)) {}
4674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFst(const Fst<A> &fst, C* mapper,
4694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             const MapFstOptions& opts)
4704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      : impl_(new MapFstImpl<A, B, C>(fst, mapper, opts)) {}
4714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFst(const Fst<A> &fst, const C &mapper)
4734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      : impl_(new MapFstImpl<A, B, C>(fst, mapper,
4744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                          MapFstOptions())) {}
4754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFst(const Fst<A> &fst, C* mapper)
4774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      : impl_(new MapFstImpl<A, B, C>(fst, mapper,
4784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                          MapFstOptions())) {}
4794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFst(const MapFst<A, B, C> &fst) : Fst<B>(fst), impl_(fst.impl_) {
4814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    impl_->IncrRefCount();
4824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  virtual ~MapFst() { if (!impl_->DecrRefCount()) delete impl_;  }
4854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  virtual StateId Start() const { return impl_->Start(); }
4874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  virtual Weight Final(StateId s) const { return impl_->Final(s); }
4894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId NumStates() const { return impl_->NumStates(); }
4914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  size_t NumArcs(StateId s) const { return impl_->NumArcs(s); }
4934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  size_t NumInputEpsilons(StateId s) const {
4954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return impl_->NumInputEpsilons(s);
4964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  size_t NumOutputEpsilons(StateId s) const {
4994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return impl_->NumOutputEpsilons(s);
5004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  virtual uint64 Properties(uint64 mask, bool test) const {
5034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (test) {
5044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      uint64 known, test = TestProperties(*this, mask, &known);
5054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      impl_->SetProperties(test, known);
5064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return test & mask;
5074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    } else {
5084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return impl_->Properties(mask);
5094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
5104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  virtual const string& Type() const { return impl_->Type(); }
5134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  virtual MapFst<A, B, C> *Copy() const {
5154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return new MapFst<A, B, C>(*this);
5164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  virtual const SymbolTable* InputSymbols() const {
5194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return impl_->InputSymbols();
5204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  virtual const SymbolTable* OutputSymbols() const {
5234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return impl_->OutputSymbols();
5244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project virtual inline void InitStateIterator(StateIteratorData<B> *data) const;
5274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  virtual void InitArcIterator(StateId s, ArcIteratorData<B> *data) const {
5294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    impl_->InitArcIterator(s, data);
5304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project private:
5334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFstImpl<A, B, C> *impl_;
5344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  void operator=(const MapFst<A, B, C> &fst);  // disallow
5364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
5374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Specialization for MapFst.
5404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate<class A, class B, class C>
5414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass StateIterator< MapFst<A, B, C> > : public StateIteratorBase<B> {
5424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project public:
5434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename B::StateId StateId;
5444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  explicit StateIterator(const MapFst<A, B, C> &fst)
5464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      : impl_(fst.impl_), siter_(*impl_->fst_), s_(0),
5474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        superfinal_(impl_->final_action_ == MAP_REQUIRE_SUPERFINAL)
5484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  { CheckSuperfinal(); }
5494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bool Done() const { return siter_.Done() && !superfinal_; }
5514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId Value() const { return s_; }
5534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  void Next() {
5554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ++s_;
5564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!siter_.Done()) {
5574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      siter_.Next();
5584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      CheckSuperfinal();
5594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
5604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if (superfinal_)
5614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      superfinal_ = false;
5624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  void Reset() {
5654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    s_ = 0;
5664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    siter_.Reset();
5674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    superfinal_ = impl_->final_action_ == MAP_REQUIRE_SUPERFINAL;
5684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    CheckSuperfinal();
5694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project private:
5724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  void CheckSuperfinal() {
5734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (impl_->final_action_ != MAP_ALLOW_SUPERFINAL || superfinal_)
5744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return;
5754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!siter_.Done()) {
5764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      B final_arc = (*impl_->mapper_)(A(0, 0, impl_->fst_->Final(s_),
5774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                           kNoStateId));
5784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (final_arc.ilabel != 0 || final_arc.olabel != 0)
5794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        superfinal_ = true;
5804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
5814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  const MapFstImpl<A, B, C> *impl_;
5844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateIterator< Fst<A> > siter_;
5854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId s_;
5864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bool superfinal_;    // true if there is a superfinal state and not done
5874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  DISALLOW_EVIL_CONSTRUCTORS(StateIterator);
5894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
5904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Specialization for MapFst.
5924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A, class B, class C>
5934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass ArcIterator< MapFst<A, B, C> >
5944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    : public CacheArcIterator< MapFst<A, B, C> > {
5954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project public:
5964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::StateId StateId;
5974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ArcIterator(const MapFst<A, B, C> &fst, StateId s)
5994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      : CacheArcIterator< MapFst<A, B, C> >(fst, s) {
6004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!fst.impl_->HasArcs(s))
6014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fst.impl_->Expand(s);
6024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project private:
6054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  DISALLOW_EVIL_CONSTRUCTORS(ArcIterator);
6064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
6074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A, class B, class C> inline
6094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid MapFst<A, B, C>::InitStateIterator(StateIteratorData<B> *data)
6104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    const {
6114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  data->base = new StateIterator< MapFst<A, B, C> >(*this);
6124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
6134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
6164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Utility Mappers
6174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
6184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper that returns its input.
6204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A>
6214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct IdentityMapper {
6224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef A FromArc;
6234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef A ToArc;
6244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  A operator()(const A &arc) const { return arc; }
6264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
6284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const { return props; }
6304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
6314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper that returns its input with final states redirected to
6344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// a single super-final state.
6354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A>
6364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct SuperFinalMapper {
6374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef A FromArc;
6384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef A ToArc;
6394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  A operator()(const A &arc) const { return arc; }
6414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_REQUIRE_SUPERFINAL; }
6434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const {
6454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return props & kAddSuperFinalProperties;
6464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
6484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper from StdArc to LogArc.
6514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct StdToLogMapper {
6524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef StdArc FromArc;
6534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef LogArc ToArc;
6544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  LogArc operator()(const StdArc &arc) const {
6564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return LogArc(arc.ilabel, arc.olabel, arc.weight.Value(), arc.nextstate);
6574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
6604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const { return props; }
6624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
6634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper from LogArc to StdArc.
6664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct LogToStdMapper {
6674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef LogArc FromArc;
6684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef StdArc ToArc;
6694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StdArc operator()(const LogArc &arc) const {
6714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return StdArc(arc.ilabel, arc.olabel, arc.weight.Value(), arc.nextstate);
6724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
6754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const { return props; }
6774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
6784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper from A to GallicArc<A>.
6814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A, StringType S = STRING_LEFT>
6824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct ToGallicMapper {
6834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef A FromArc;
6844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef GallicArc<A, S> ToArc;
6854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef StringWeight<typename A::Label, S> SW;
6874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::Weight AW;
6884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename GallicArc<A, S>::Weight GW;
6894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ToArc operator()(const A &arc) const {
6914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // 'Super-final' arc.
6924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (arc.nextstate == kNoStateId && arc.weight != AW::Zero())
6934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return ToArc(0, 0, GW(SW::One(), arc.weight), kNoStateId);
6944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // 'Super-non-final' arc.
6954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if (arc.nextstate == kNoStateId)
6964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return ToArc(0, 0, GW(SW::Zero(), arc.weight), kNoStateId);
6974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // Epsilon label.
6984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if (arc.olabel == 0)
6994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return ToArc(arc.ilabel, arc.ilabel,
7004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   GW(SW::One(), arc.weight), arc.nextstate);
7014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // Regular label.
7024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else
7034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return ToArc(arc.ilabel, arc.ilabel,
7044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   GW(SW(arc.olabel), arc.weight), arc.nextstate);
7054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
7084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const {
7104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ProjectProperties(props, true) & kWeightInvariantProperties;
7114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
7134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper from GallicArc<A> to A.
7164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A, StringType S = STRING_LEFT>
7174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct FromGallicMapper {
7184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef GallicArc<A, S> FromArc;
7194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef A ToArc;
7204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::Label Label;
7224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef StringWeight<Label, S> SW;
7234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::Weight AW;
7244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename GallicArc<A, S>::Weight GW;
7254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  A operator()(const FromArc &arc) const {
7274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // 'Super-non-final' arc.
7284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (arc.nextstate == kNoStateId && arc.weight == GW::Zero())
7294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return A(arc.ilabel, 0, AW::Zero(), kNoStateId);
7304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SW w1 = arc.weight.Value1();
7324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    AW w2 = arc.weight.Value2();
7334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    StringWeightIterator<Label, S> iter1(w1);
7344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    Label l = w1.Size() == 1 ? iter1.Value() : 0;
7364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    CHECK(l != kStringInfinity);
7384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    CHECK(l != kStringBad);
7394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    CHECK(arc.ilabel == arc.olabel);
7404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    CHECK(w1.Size() <= 1);
7414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return A(arc.ilabel, l, w2, arc.nextstate);
7434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_ALLOW_SUPERFINAL; }
7464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const {
7484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return props & kOLabelInvariantProperties &
7494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      kWeightInvariantProperties & kAddSuperFinalProperties;
7504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
7524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper from GallicArc<A> to A.
7554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A, StringType S = STRING_LEFT>
7564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct GallicToNewSymbolsMapper {
7574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef GallicArc<A, S> FromArc;
7584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef A ToArc;
7594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::StateId StateId;
7614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::Label Label;
7624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef StringWeight<Label, S> SW;
7634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::Weight AW;
7644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename GallicArc<A, S>::Weight GW;
7654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  GallicToNewSymbolsMapper(MutableFst<ToArc> *fst)
7674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      : fst_(fst), lmax_(0), osymbols_(fst->OutputSymbols()), isymbols_(0) {
7684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fst_->DeleteStates();
7694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    state_ = fst_->AddState();
7704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fst_->SetStart(state_);
7714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fst_->SetFinal(state_, AW::One());
7724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (osymbols_) {
7734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      string name = osymbols_->Name() + "_from_gallic";
7744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      isymbols_ = new SymbolTable(name);
7754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      isymbols_->AddSymbol(osymbols_->Find((int64) 0), 0);
7764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   }
7774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fst_->SetInputSymbols(isymbols_);
7784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  A operator()(const FromArc &arc) {
7814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // 'Super-non-final' arc.
7824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (arc.nextstate == kNoStateId && arc.weight == GW::Zero())
7834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return A(arc.ilabel, 0, AW::Zero(), kNoStateId);
7844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SW w1 = arc.weight.Value1();
7864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    AW w2 = arc.weight.Value2();
7874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    Label l;
7884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (w1.Size() == 0) {
7904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      l = 0;
7914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    } else {
7924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      typename Map::iterator miter = map_.find(w1);
7934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (miter != map_.end()) {
7944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        l = (*miter).second;
7954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      } else {
7964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        l = ++lmax_;
7974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        map_.insert(pair<const SW, Label>(w1, l));
7984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        StringWeightIterator<Label, S> iter1(w1);
7994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        StateId n;
8004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        string s;
8014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        for(ssize_t i = 0, p = state_;
8024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            i < w1.Size();
8034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            ++i, iter1.Next(), p = n) {
8044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          n = i == w1.Size() - 1 ? state_ : fst_->AddState();
8054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          fst_->AddArc(p, ToArc(i ? 0 : l, iter1.Value(), AW::One(), n));
8064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (isymbols_) {
8074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            if (i) s = s + "_";
8084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            s = s + osymbols_->Find(iter1.Value());
8094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
8104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
8114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (isymbols_)
8124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          isymbols_->AddSymbol(s, l);
8134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
8144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
8154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    CHECK(l != kStringInfinity);
8174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    CHECK(l != kStringBad);
8184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    CHECK(arc.ilabel == arc.olabel);
8194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return A(arc.ilabel, l, w2, arc.nextstate);
8214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_ALLOW_SUPERFINAL; }
8244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const {
8264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return props & kOLabelInvariantProperties &
8274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      kWeightInvariantProperties & kAddSuperFinalProperties;
8284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project private:
8314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  class StringKey {
8324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   public:
8334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    size_t operator()(const SW &x) const {
8344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return x.Hash();
8354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
8364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  };
8374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
83873018b4a1d088cdda0e7bd059fddf1f308a8195aIan Rogers  typedef std::unordered_map<SW, Label, StringKey> Map;
8394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MutableFst<ToArc> *fst_;
8414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Map map_;
8424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Label lmax_;
8434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId state_;
8444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  SymbolTable *osymbols_, *isymbols_;
8454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
8464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper to add a constant to all weights.
8494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A>
8504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct PlusMapper {
8514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::Weight Weight;
8524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  explicit PlusMapper(Weight w) : weight_(w) {}
8544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  A operator()(const A &arc) const {
8564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (arc.weight == Weight::Zero())
8574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return arc;
8584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    Weight w = Plus(arc.weight, weight_);
8594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return A(arc.ilabel, arc.olabel, w, arc.nextstate);
8604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
8634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const {
8654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return props & kWeightInvariantProperties;
8664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Weight weight_;
8694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
8704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper to (right) multiply a constant to all weights.
8734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A>
8744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct TimesMapper {
8754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename A::Weight Weight;
8764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  explicit TimesMapper(Weight w) : weight_(w) {}
8784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  A operator()(const A &arc) const {
8804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (arc.weight == Weight::Zero())
8814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return arc;
8824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    Weight w = Times(arc.weight, weight_);
8834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return A(arc.ilabel, arc.olabel, w, arc.nextstate);
8844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
8874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const {
8894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return props & kWeightInvariantProperties;
8904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Weight weight_;
8934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
8944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper to map all non-Zero() weights to One().
8974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A, class B = A>
8984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct RmWeightMapper {
8994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef A FromArc;
9004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef B ToArc;
9014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename FromArc::Weight FromWeight;
9024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename ToArc::Weight ToWeight;
9034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  B operator()(const A &arc) const {
9054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ToWeight w = arc.weight != FromWeight::Zero() ?
9064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   ToWeight::One() : ToWeight::Zero();
9074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return B(arc.ilabel, arc.olabel, w, arc.nextstate);
9084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
9094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
9114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const {
9134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return props & kWeightInvariantProperties | kUnweighted;
9144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
9154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
9164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper to quantize all weights.
9194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A, class B = A>
9204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct QuantizeMapper {
9214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef A FromArc;
9224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef B ToArc;
9234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename FromArc::Weight FromWeight;
9244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename ToArc::Weight ToWeight;
9254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  QuantizeMapper() : delta_(kDelta) {}
9274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  explicit QuantizeMapper(float d) : delta_(d) {}
9294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  B operator()(const A &arc) const {
9314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ToWeight w = arc.weight.Quantize(delta_);
9324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return B(arc.ilabel, arc.olabel, w, arc.nextstate);
9334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
9344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
9364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const {
9384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return props & kWeightInvariantProperties;
9394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
9404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  float delta_;
9424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
9434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Mapper from A to B under the assumption:
9464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//    B::Weight = A::Weight::ReverseWeight
9474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//    B::Label == A::Label
9484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//    B::StateId == A::StateId
9494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// The weight is reversed, while the label and nextstate preserved
9504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// in the mapping.
9514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A, class B>
9524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct ReverseWeightMapper {
9534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef A FromArc;
9544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef B ToArc;
9554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  B operator()(const A &arc) const {
9574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return B(arc.ilabel, arc.olabel, arc.weight.Reverse(), arc.nextstate);
9584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
9594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
9614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 Properties(uint64 props) const { return props; }
9634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
9644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}  // namespace fst
9664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif  // FST_LIB_MAP_H__
968