1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// tuple-weight.h
2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License");
4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License.
5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at
6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     http://www.apache.org/licenses/LICENSE-2.0
8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software
10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS,
11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and
13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License.
14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc.
16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: allauzen@google (Cyril Allauzen)
17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// \file
19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Tuple weight set operation definitions.
20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_LIB_TUPLE_WEIGHT_H__
22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_LIB_TUPLE_WEIGHT_H__
23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <string>
25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <vector>
26f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonusing std::vector;
27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/weight.h>
29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian HodsonDECLARE_string(fst_weight_parentheses);
32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian HodsonDECLARE_string(fst_weight_separator);
33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst {
35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class W, unsigned int n> class TupleWeight;
37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, unsigned int n>
38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonistream &operator>>(istream &strm, TupleWeight<W, n> &w);
39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// n-tuple weight, element of the n-th catersian power of W
41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, unsigned int n>
42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass TupleWeight {
43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef TupleWeight<typename W::ReverseWeight, n> ReverseWeight;
45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TupleWeight() {}
47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TupleWeight(const TupleWeight &w) {
49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t i = 0; i < n; ++i)
50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      values_[i] = w.values_[i];
51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  template <class Iterator>
54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TupleWeight(Iterator begin, Iterator end) {
55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (Iterator iter = begin; iter != end; ++iter)
56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      values_[iter - begin] = *iter;
57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TupleWeight(const W &w) {
60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t i = 0; i < n; ++i)
61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      values_[i] = w;
62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const TupleWeight<W, n> &Zero() {
65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const TupleWeight<W, n> zero(W::Zero());
66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return zero;
67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const TupleWeight<W, n> &One() {
70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const TupleWeight<W, n> one(W::One());
71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return one;
72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const TupleWeight<W, n> &NoWeight() {
75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const TupleWeight<W, n> no_weight(W::NoWeight());
76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return no_weight;
77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static unsigned int Length() {
80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return n;
81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  istream &Read(istream &strm) {
84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t i = 0; i < n; ++i)
85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      values_[i].Read(strm);
86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return strm;
87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ostream &Write(ostream &strm) const {
90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t i = 0; i < n; ++i)
91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      values_[i].Write(strm);
92f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return strm;
93f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
94f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
95f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TupleWeight<W, n> &operator=(const TupleWeight<W, n> &w) {
96f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t i = 0; i < n; ++i)
97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      values_[i] = w.values_[i];
98f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return *this;
99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Member() const {
102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    bool member = true;
103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t i = 0; i < n; ++i)
104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      member = member && values_[i].Member();
105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return member;
106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  size_t Hash() const {
109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    uint64 hash = 0;
110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t i = 0; i < n; ++i)
111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      hash = 5 * hash + values_[i].Hash();
112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return size_t(hash);
113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TupleWeight<W, n> Quantize(float delta = kDelta) const {
116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    TupleWeight<W, n> w;
117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t i = 0; i < n; ++i)
118f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      w.values_[i] = values_[i].Quantize(delta);
119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w;
120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ReverseWeight Reverse() const {
123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    TupleWeight<W, n> w;
124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t i = 0; i < n; ++i)
125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      w.values_[i] = values_[i].Reverse();
126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w;
127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const W& Value(size_t i) const { return values_[i]; }
130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void SetValue(size_t i, const W &w) { values_[i] = w; }
132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson protected:
134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Reads TupleWeight when there are no parentheses around tuple terms
135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  inline static istream &ReadNoParen(istream &strm,
136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                     TupleWeight<W, n> &w,
137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                     char separator) {
138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    int c;
139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    do {
140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      c = strm.get();
141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } while (isspace(c));
142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t i = 0; i < n - 1; ++i) {
144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      string s;
145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (i)
146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        c = strm.get();
147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      while (c != separator) {
148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (c == EOF) {
149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          strm.clear(std::ios::badbit);
150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          return strm;
151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        s += c;
153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        c = strm.get();
154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      // read (i+1)-th element
156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      istringstream sstrm(s);
157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      W r = W::Zero();
158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      sstrm >> r;
159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      w.SetValue(i, r);
160f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
161f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
162f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // read n-th element
163f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    W r = W::Zero();
164f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    strm >> r;
165f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    w.SetValue(n - 1, r);
166f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
167f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return strm;
168f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
169f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
170f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Reads TupleWeight when there are parentheses around tuple terms
171f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  inline static istream &ReadWithParen(istream &strm,
172f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                       TupleWeight<W, n> &w,
173f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                       char separator,
174f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                       char open_paren,
175f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                       char close_paren) {
176f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    int c;
177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    do {
178f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      c = strm.get();
179f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } while (isspace(c));
180f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
181f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (c != open_paren) {
182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << " is fst_weight_parentheses flag set correcty? ";
183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      strm.clear(std::ios::badbit);
184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return strm;
185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t i = 0; i < n - 1; ++i) {
188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      // read (i+1)-th element
189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      stack<int> parens;
190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      string s;
191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      c = strm.get();
192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      while (c != separator || !parens.empty()) {
193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (c == EOF) {
194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          strm.clear(std::ios::badbit);
195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          return strm;
196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        s += c;
198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        // if parens encountered before separator, they must be matched
199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (c == open_paren) {
200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          parens.push(1);
201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        } else if (c == close_paren) {
202f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          // Fail for mismatched parens
203f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (parens.empty()) {
204f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            strm.clear(std::ios::failbit);
205f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            return strm;
206f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          }
207f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          parens.pop();
208f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
209f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        c = strm.get();
210f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
211f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      istringstream sstrm(s);
212f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      W r = W::Zero();
213f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      sstrm >> r;
214f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      w.SetValue(i, r);
215f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
216f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
217f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // read n-th element
218f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    string s;
219f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    c = strm.get();
220f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    while (c != EOF) {
221f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      s += c;
222f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      c = strm.get();
223f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
224f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (s.empty() || *s.rbegin() != close_paren) {
225f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << " is fst_weight_parentheses flag set correcty? ";
226f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      strm.clear(std::ios::failbit);
227f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return strm;
228f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
229f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    s.erase(s.size() - 1, 1);
230f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    istringstream sstrm(s);
231f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    W r = W::Zero();
232f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    sstrm >> r;
233f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    w.SetValue(n - 1, r);
234f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
235f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return strm;
236f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
237f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
238f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
239f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
240f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  W values_[n];
241f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
242f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  friend istream &operator>><W, n>(istream&, TupleWeight<W, n>&);
243f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
244f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
245f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, unsigned int n>
246f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool operator==(const TupleWeight<W, n> &w1,
247f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       const TupleWeight<W, n> &w2) {
248f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool equal = true;
249f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (size_t i = 0; i < n; ++i)
250f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    equal = equal && (w1.Value(i) == w2.Value(i));
251f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return equal;
252f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
253f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
254f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, unsigned int n>
255f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool operator!=(const TupleWeight<W, n> &w1,
256f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       const TupleWeight<W, n> &w2) {
257f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool not_equal = false;
258f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (size_t i = 0; (i < n) && !not_equal; ++i)
259f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    not_equal = not_equal || (w1.Value(i) != w2.Value(i));
260f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return not_equal;
261f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
262f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
263f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, unsigned int n>
264f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool ApproxEqual(const TupleWeight<W, n> &w1,
265f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                        const TupleWeight<W, n> &w2,
266f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                        float delta = kDelta) {
267f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool approx_equal = true;
268f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (size_t i = 0; i < n; ++i)
269f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    approx_equal = approx_equal &&
270f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        ApproxEqual(w1.Value(i), w2.Value(i), delta);
271f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return approx_equal;
272f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
273f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
274f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, unsigned int n>
275f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline ostream &operator<<(ostream &strm, const TupleWeight<W, n> &w) {
276f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if(FLAGS_fst_weight_separator.size() != 1) {
277f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    FSTERROR() << "FLAGS_fst_weight_separator.size() is not equal to 1";
278f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    strm.clear(std::ios::badbit);
279f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return strm;
280f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
281f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  char separator = FLAGS_fst_weight_separator[0];
282f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool write_parens = false;
283f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!FLAGS_fst_weight_parentheses.empty()) {
284f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (FLAGS_fst_weight_parentheses.size() != 2) {
285f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "FLAGS_fst_weight_parentheses.size() is not equal to 2";
286f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      strm.clear(std::ios::badbit);
287f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return strm;
288f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
289f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    write_parens = true;
290f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
291f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
292f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (write_parens)
293f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    strm << FLAGS_fst_weight_parentheses[0];
294f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (size_t i  = 0; i < n; ++i) {
295f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if(i)
296f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      strm << separator;
297f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    strm << w.Value(i);
298f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
299f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (write_parens)
300f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    strm << FLAGS_fst_weight_parentheses[1];
301f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
302f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return strm;
303f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
304f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
305f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W, unsigned int n>
306f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline istream &operator>>(istream &strm, TupleWeight<W, n> &w) {
307f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if(FLAGS_fst_weight_separator.size() != 1) {
308f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    FSTERROR() << "FLAGS_fst_weight_separator.size() is not equal to 1";
309f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    strm.clear(std::ios::badbit);
310f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return strm;
311f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
312f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  char separator = FLAGS_fst_weight_separator[0];
313f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
314f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!FLAGS_fst_weight_parentheses.empty()) {
315f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (FLAGS_fst_weight_parentheses.size() != 2) {
316f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "FLAGS_fst_weight_parentheses.size() is not equal to 2";
317f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      strm.clear(std::ios::badbit);
318f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return strm;
319f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
320f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return TupleWeight<W, n>::ReadWithParen(
321f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        strm, w, separator, FLAGS_fst_weight_parentheses[0],
322f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        FLAGS_fst_weight_parentheses[1]);
323f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else {
324f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return TupleWeight<W, n>::ReadNoParen(strm, w, separator);
325f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
326f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
327f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
328f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
329f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
330f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}  // namespace fst
331f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
332f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif  // FST_LIB_TUPLE_WEIGHT_H__
333