1 // product-weight.h
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 //
16 // \file
17 // Product weight set and associated semiring operation definitions.
18
19 #ifndef FST_LIB_PRODUCT_WEIGHT_H__
20 #define FST_LIB_PRODUCT_WEIGHT_H__
21
22 #include "fst/lib/weight.h"
23
24 DECLARE_string(fst_product_separator);
25
26 namespace fst {
27
28 // Product semiring: W1 * W2
29 template<class W1, class W2>
30 class ProductWeight {
31 public:
32 typedef ProductWeight<typename W1::ReverseWeight, typename W2::ReverseWeight>
33 ReverseWeight;
34
ProductWeight()35 ProductWeight() {}
36
ProductWeight(W1 w1,W2 w2)37 ProductWeight(W1 w1, W2 w2) : value1_(w1), value2_(w2) {}
38
Zero()39 static const ProductWeight<W1, W2> &Zero() {
40 static const ProductWeight<W1, W2> zero(W1::Zero(), W2::Zero());
41 return zero;
42 }
43
One()44 static const ProductWeight<W1, W2> &One() {
45 static const ProductWeight<W1, W2> one(W1::One(), W2::One());
46 return one;
47 }
48
Type()49 static const string &Type() {
50 static const string type = W1::Type() + "_X_" + W2::Type();
51 return type;
52 }
53
Read(istream & strm)54 istream &Read(istream &strm) {
55 value1_.Read(strm);
56 return value2_.Read(strm);
57 }
58
Write(ostream & strm)59 ostream &Write(ostream &strm) const {
60 value1_.Write(strm);
61 return value2_.Write(strm);
62 }
63
64 ProductWeight<W1, W2> &operator=(const ProductWeight<W1, W2> &w) {
65 value1_ = w.Value1();
66 value2_ = w.Value2();
67 return *this;
68 }
69
Member()70 bool Member() const { return value1_.Member() && value2_.Member(); }
71
Hash()72 ssize_t Hash() const {
73 ssize_t h1 = value1_.Hash();
74 ssize_t h2 = value2_.Hash();
75 int lshift = 5;
76 int rshift = sizeof(ssize_t) - 5;
77 return h1 << lshift ^ h1 >> rshift ^ h2;
78 }
79
80 ProductWeight<W1, W2> Quantize(float delta = kDelta) const {
81 return ProductWeight<W1, W2>(value1_.Quantize(), value2_.Quantize());
82 }
83
Reverse()84 ReverseWeight Reverse() const {
85 return ReverseWeight(value1_.Reverse(), value2_.Reverse());
86 }
87
Properties()88 static uint64 Properties() {
89 uint64 props1 = W1::Properties();
90 uint64 props2 = W2::Properties();
91 return props1 & props2 & (kLeftSemiring | kRightSemiring |
92 kCommutative | kIdempotent);
93 }
94
Value1()95 W1 Value1() const { return value1_; }
96
Value2()97 W2 Value2() const { return value2_; }
98
99 private:
100 W1 value1_;
101 W2 value2_;
102 };
103
104 template <class W1, class W2>
105 inline bool operator==(const ProductWeight<W1, W2> &w,
106 const ProductWeight<W1, W2> &v) {
107 return w.Value1() == v.Value1() && w.Value2() == v.Value2();
108 }
109
110 template <class W1, class W2>
111 inline bool operator!=(const ProductWeight<W1, W2> &w1,
112 const ProductWeight<W1, W2> &w2) {
113 return w1.Value1() != w2.Value1() || w1.Value2() != w2.Value2();
114 }
115
116
117 template <class W1, class W2>
118 inline bool ApproxEqual(const ProductWeight<W1, W2> &w1,
119 const ProductWeight<W1, W2> &w2,
120 float delta = kDelta) {
121 return w1 == w2;
122 }
123
124 template <class W1, class W2>
125 inline ostream &operator<<(ostream &strm, const ProductWeight<W1, W2> &w) {
126 CHECK(FLAGS_fst_product_separator.size() == 1);
127 char separator = FLAGS_fst_product_separator[0];
128 return strm << w.Value1() << separator << w.Value2();
129 }
130
131 template <class W1, class W2>
132 inline istream &operator>>(istream &strm, ProductWeight<W1, W2> &w) {
133 CHECK(FLAGS_fst_product_separator.size() == 1);
134 char separator = FLAGS_fst_product_separator[0];
135 int c;
136
137 // read any initial whitespapce
138 while (true) {
139 c = strm.get();
140 if (c == EOF || c == separator) {
141 strm.clear(std::ios::badbit);
142 return strm;
143 }
144 if (!isspace(c))
145 break;
146 }
147
148 // read first element
149 string s1;
150 do {
151 s1 += c;
152 c = strm.get();
153 if (c == EOF || isspace(c)) {
154 strm.clear(std::ios::badbit);
155 return strm;
156 }
157 } while (c != separator);
158 istringstream strm1(s1);
159 W1 w1 = W1::Zero();
160 strm1 >> w1;
161
162 // read second element
163 W2 w2 = W2::Zero();
164 strm >> w2;
165
166 w = ProductWeight<W1, W2>(w1, w2);
167 return strm;
168 }
169
170 template <class W1, class W2>
Plus(const ProductWeight<W1,W2> & w,const ProductWeight<W1,W2> & v)171 inline ProductWeight<W1, W2> Plus(const ProductWeight<W1, W2> &w,
172 const ProductWeight<W1, W2> &v) {
173 return ProductWeight<W1, W2>(Plus(w.Value1(), v.Value1()),
174 Plus(w.Value2(), v.Value2()));
175 }
176
177 template <class W1, class W2>
Times(const ProductWeight<W1,W2> & w,const ProductWeight<W1,W2> & v)178 inline ProductWeight<W1, W2> Times(const ProductWeight<W1, W2> &w,
179 const ProductWeight<W1, W2> &v) {
180 return ProductWeight<W1, W2>(Times(w.Value1(), v.Value1()),
181 Times(w.Value2(), v.Value2()));
182 }
183
184 template <class W1, class W2>
185 inline ProductWeight<W1, W2> Divide(const ProductWeight<W1, W2> &w,
186 const ProductWeight<W1, W2> &v,
187 DivideType typ = DIVIDE_ANY) {
188 return ProductWeight<W1, W2>(Divide(w.Value1(), v.Value1(), typ),
189 Divide(w.Value2(), v.Value2(), typ));
190 }
191
192 } // namespace fst;
193
194 #endif // FST_LIB_PRODUCT_WEIGHT_H__
195