• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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