14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// test-properties.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// Functions to manipulate and test property bits
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifndef FST_LIB_TEST_PROPERTIES_H__
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define FST_LIB_TEST_PROPERTIES_H__
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <ext/hash_set>
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectusing __gnu_cxx::hash_set;
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/connect.h"
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/dfs-visit.h"
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/mutable-fst.h"
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectDECLARE_bool(fst_verify_properties);
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectnamespace fst {
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// For a binary property, the bit is always returned set.
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// For a trinary (i.e. two-bit) property, both bits are
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// returned set iff either corresponding input bit is set.
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline uint64 KnownProperties(uint64 props) {
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return kBinaryProperties | props & kTrinaryProperties |
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    (props & kPosTrinaryProperties) << 1 |
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    (props & kNegTrinaryProperties) >> 1;
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Tests compatibility between two sets of properties
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline bool CompatProperties(uint64 props1, uint64 props2) {
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 known_props1 = KnownProperties(props1);
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 known_props2 = KnownProperties(props2);
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 known_props = known_props1 & known_props2;
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 incompat_props = (props1 & known_props) ^ (props2 & known_props);
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (incompat_props) {
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    uint64 prop = 1;
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (int i = 0; i < 64; ++i, prop <<= 1)
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (prop & incompat_props)
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        LOG(ERROR) << "CompatProperties: mismatch: " << PropertyNames[i]
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << ": props1 = " << (props1 & prop ? "true" : "false")
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << ", props2 = " << (props2 & prop ? "true" : "false");
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return false;
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  } else {
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return true;
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Computes FST property values defined in properties.h.  The value of
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// each property indicated in the mask will be determined and returned
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// (these will never be unknown here). In the course of determining
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// the properties specifically requested in the mask, certain other
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// properties may be determined (those with little additional expense)
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// and their values will be returned as well. The complete set of
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// known properties (whether true or false) determined by this
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// operation will be assigned to the the value pointed to by KNOWN.
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// If 'use_stored' is true, pre-computed FST properties may be used
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// when possible. This routine is seldom called directly; instead it
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// is used to implement fst.Properties(mask, true).
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate<class Arc>
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectuint64 ComputeProperties(const Fst<Arc> &fst, uint64 mask, uint64 *known,
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                         bool use_stored) {
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename Arc::Label Label;
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename Arc::Weight Weight;
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename Arc::StateId StateId;
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 fst_props = fst.Properties(kFstProperties, false);  // Fst-stored
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Check stored FST properties first if allowed.
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (use_stored) {
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    uint64 known_props = KnownProperties(fst_props);
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // If FST contains required info, return it.
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if ((known_props & mask) == mask) {
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *known = known_props;
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return fst_props;
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Compute (trinary) properties explicitly.
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Initialize with binary properties (already known).
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 comp_props = fst_props & kBinaryProperties;
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Compute these trinary properties with a DFS. We compute only those
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // that need a DFS here, since we otherwise would like to avoid a DFS
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // since its stack could grow large.
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 dfs_props = kCyclic | kAcyclic | kInitialCyclic | kInitialAcyclic |
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                     kAccessible | kNotAccessible |
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                     kCoAccessible | kNotCoAccessible;
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (mask & dfs_props) {
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SccVisitor<Arc> scc_visitor(&comp_props);
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    DfsVisit(fst, &scc_visitor);
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Compute any remaining trinary properties via a state and arcs iterations
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (mask & ~(kBinaryProperties | dfs_props)) {
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    comp_props |= kAcceptor | kNoEpsilons | kNoIEpsilons | kNoOEpsilons |
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        kILabelSorted | kOLabelSorted | kUnweighted | kTopSorted | kString;
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (mask & (kIDeterministic | kNonIDeterministic))
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      comp_props |= kIDeterministic;
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (mask & (kODeterministic | kNonODeterministic))
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      comp_props |= kODeterministic;
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    hash_set<Label> *ilabels = 0;
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    hash_set<Label> *olabels = 0;
1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    StateId nfinal = 0;
1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (StateIterator< Fst<Arc> > siter(fst);
1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         !siter.Done();
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         siter.Next()) {
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      StateId s = siter.Value();
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      Arc prev_arc(kNoLabel, kNoLabel, Weight::One(), 0);
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      // Create these only if we need to
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (mask & (kIDeterministic | kNonIDeterministic))
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ilabels = new hash_set<Label>;
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (mask & (kODeterministic | kNonODeterministic))
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        olabels = new hash_set<Label>;
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      for (ArcIterator< Fst<Arc> > aiter(fst, s);
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project           !aiter.Done();
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project           aiter.Next()) {
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        const Arc &arc =aiter.Value();
1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (ilabels && ilabels->find(arc.ilabel) != ilabels->end()) {
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kNonIDeterministic;
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kIDeterministic;
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (olabels && olabels->find(arc.olabel) != olabels->end()) {
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kNonODeterministic;
1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kODeterministic;
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (arc.ilabel != arc.olabel) {
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kNotAcceptor;
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kAcceptor;
1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (arc.ilabel == 0 && arc.olabel == 0) {
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kEpsilons;
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kNoEpsilons;
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (arc.ilabel == 0) {
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kIEpsilons;
1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kNoIEpsilons;
1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (arc.olabel == 0) {
1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kOEpsilons;
1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kNoOEpsilons;
1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (prev_arc.ilabel != kNoLabel && arc.ilabel < prev_arc.ilabel) {
1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kNotILabelSorted;
1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kILabelSorted;
1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (prev_arc.olabel != kNoLabel && arc.olabel < prev_arc.olabel) {
1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kNotOLabelSorted;
1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kOLabelSorted;
1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (arc.weight != Weight::One() && arc.weight != Weight::Zero()) {
1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kWeighted;
1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kUnweighted;
1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (arc.nextstate <= s) {
1754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kNotTopSorted;
1764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kTopSorted;
1774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (arc.nextstate != s + 1) {
1794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kNotString;
1804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kString;
1814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
1824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        prev_arc = arc;
1834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (ilabels)
1844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ilabels->insert(arc.ilabel);
1854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (olabels)
1864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          olabels->insert(arc.olabel);
1874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
1884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (nfinal > 0) {             // final state not last
1904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        comp_props |= kNotString;
1914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        comp_props &= ~kString;
1924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
1934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      Weight final = fst.Final(s);
1954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (final != Weight::Zero()) {  // final state
1974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (final != Weight::One()) {
1984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kWeighted;
1994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kUnweighted;
2004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
2014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ++nfinal;
2024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      } else {                        // non-final state
2034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fst.NumArcs(s) != 1) {
2044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props |= kNotString;
2054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          comp_props &= ~kString;
2064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
2074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
2084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      delete ilabels;
2104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      delete olabels;
2114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (fst.Start() != kNoStateId && fst.Start() != 0) {
2144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      comp_props |= kNotString;
2154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      comp_props &= ~kString;
2164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *known = KnownProperties(comp_props);
2204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return comp_props;
2214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// This is a wrapper around ComputeProperties that will cause a fatal
2244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// error if the stored properties and the computed properties are
2254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// incompatible when 'FLAGS_fst_verify_properties' is true.  This
2264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// routine is seldom called directly; instead it is used to implement
2274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// fst.Properties(mask, true).
2284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate<class Arc>
2294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectuint64 TestProperties(const Fst<Arc> &fst, uint64 mask, uint64 *known) {
2304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (FLAGS_fst_verify_properties) {
2314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    uint64 stored_props = fst.Properties(kFstProperties, false);
2324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    uint64 computed_props = ComputeProperties(fst, mask, known, false);
2334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!CompatProperties(stored_props, computed_props))
2344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      LOG(FATAL) << "TestProperties: stored Fst properties incorrect"
2354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                 << " (stored: props1, computed: props2)";
2364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return computed_props;
2374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  } else {
2384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ComputeProperties(fst, mask, known, true);
2394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}  // namespace fst
2434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif  // FST_LIB_TEST_PROPERTIES_H__
245