1 // pair-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 // Copyright 2005-2010 Google, Inc. 16 // Author: shumash@google.com (Masha Maria Shugrina) 17 // 18 // \file 19 // Pair weight templated base class for weight classes that 20 // contain two weights (e.g. Product, Lexicographic) 21 22 #ifndef FST_LIB_PAIR_WEIGHT_H_ 23 #define FST_LIB_PAIR_WEIGHT_H_ 24 25 #include <climits> 26 #include <stack> 27 #include <string> 28 29 #include <fst/weight.h> 30 31 32 DECLARE_string(fst_weight_parentheses); 33 DECLARE_string(fst_weight_separator); 34 35 namespace fst { 36 37 template<class W1, class W2> class PairWeight; 38 template <class W1, class W2> 39 istream &operator>>(istream &strm, PairWeight<W1, W2> &w); 40 41 template<class W1, class W2> 42 class PairWeight { 43 public: 44 friend istream &operator>><W1, W2>(istream&, PairWeight<W1, W2>&); 45 46 typedef PairWeight<typename W1::ReverseWeight, 47 typename W2::ReverseWeight> 48 ReverseWeight; 49 PairWeight()50 PairWeight() {} 51 PairWeight(const PairWeight & w)52 PairWeight(const PairWeight& w) : value1_(w.value1_), value2_(w.value2_) {} 53 PairWeight(W1 w1,W2 w2)54 PairWeight(W1 w1, W2 w2) : value1_(w1), value2_(w2) {} 55 Zero()56 static const PairWeight<W1, W2> &Zero() { 57 static const PairWeight<W1, W2> zero(W1::Zero(), W2::Zero()); 58 return zero; 59 } 60 One()61 static const PairWeight<W1, W2> &One() { 62 static const PairWeight<W1, W2> one(W1::One(), W2::One()); 63 return one; 64 } 65 NoWeight()66 static const PairWeight<W1, W2> &NoWeight() { 67 static const PairWeight<W1, W2> no_weight(W1::NoWeight(), W2::NoWeight()); 68 return no_weight; 69 } 70 Read(istream & strm)71 istream &Read(istream &strm) { 72 value1_.Read(strm); 73 return value2_.Read(strm); 74 } 75 Write(ostream & strm)76 ostream &Write(ostream &strm) const { 77 value1_.Write(strm); 78 return value2_.Write(strm); 79 } 80 81 PairWeight<W1, W2> &operator=(const PairWeight<W1, W2> &w) { 82 value1_ = w.Value1(); 83 value2_ = w.Value2(); 84 return *this; 85 } 86 Member()87 bool Member() const { return value1_.Member() && value2_.Member(); } 88 Hash()89 size_t Hash() const { 90 size_t h1 = value1_.Hash(); 91 size_t h2 = value2_.Hash(); 92 const int lshift = 5; 93 const int rshift = CHAR_BIT * sizeof(size_t) - 5; 94 return h1 << lshift ^ h1 >> rshift ^ h2; 95 } 96 97 PairWeight<W1, W2> Quantize(float delta = kDelta) const { 98 return PairWeight<W1, W2>(value1_.Quantize(delta), 99 value2_.Quantize(delta)); 100 } 101 Reverse()102 ReverseWeight Reverse() const { 103 return ReverseWeight(value1_.Reverse(), value2_.Reverse()); 104 } 105 Value1()106 const W1& Value1() const { return value1_; } 107 Value2()108 const W2& Value2() const { return value2_; } 109 110 protected: SetValue1(const W1 & w)111 void SetValue1(const W1 &w) { value1_ = w; } SetValue2(const W2 & w)112 void SetValue2(const W2 &w) { value2_ = w; } 113 114 // Reads PairWeight when there are not parentheses around pair terms ReadNoParen(istream & strm,PairWeight<W1,W2> & w,char separator)115 inline static istream &ReadNoParen( 116 istream &strm, PairWeight<W1, W2>& w, char separator) { 117 int c; 118 do { 119 c = strm.get(); 120 } while (isspace(c)); 121 122 string s1; 123 while (c != separator) { 124 if (c == EOF) { 125 strm.clear(std::ios::badbit); 126 return strm; 127 } 128 s1 += c; 129 c = strm.get(); 130 } 131 istringstream strm1(s1); 132 W1 w1 = W1::Zero(); 133 strm1 >> w1; 134 135 // read second element 136 W2 w2 = W2::Zero(); 137 strm >> w2; 138 139 w = PairWeight<W1, W2>(w1, w2); 140 return strm; 141 } 142 143 // Reads PairWeight when there are parentheses around pair terms ReadWithParen(istream & strm,PairWeight<W1,W2> & w,char separator,char open_paren,char close_paren)144 inline static istream &ReadWithParen( 145 istream &strm, PairWeight<W1, W2>& w, 146 char separator, char open_paren, char close_paren) { 147 int c; 148 do { 149 c = strm.get(); 150 } while (isspace(c)); 151 if (c != open_paren) { 152 FSTERROR() << " is fst_weight_parentheses flag set correcty? "; 153 strm.clear(std::ios::failbit); 154 return strm; 155 } 156 c = strm.get(); 157 158 // read first element 159 stack<int> parens; 160 string s1; 161 while (c != separator || !parens.empty()) { 162 if (c == EOF) { 163 strm.clear(std::ios::badbit); 164 return strm; 165 } 166 s1 += c; 167 // if parens encountered before separator, they must be matched 168 if (c == open_paren) { 169 parens.push(1); 170 } else if (c == close_paren) { 171 // Fail for mismatched parens 172 if (parens.empty()) { 173 strm.clear(std::ios::failbit); 174 return strm; 175 } 176 parens.pop(); 177 } 178 c = strm.get(); 179 } 180 istringstream strm1(s1); 181 W1 w1 = W1::Zero(); 182 strm1 >> w1; 183 184 // read second element 185 string s2; 186 c = strm.get(); 187 while (c != EOF) { 188 s2 += c; 189 c = strm.get(); 190 } 191 if (s2.empty() || (s2[s2.size() - 1] != close_paren)) { 192 FSTERROR() << " is fst_weight_parentheses flag set correcty? "; 193 strm.clear(std::ios::failbit); 194 return strm; 195 } 196 197 s2.erase(s2.size() - 1, 1); 198 istringstream strm2(s2); 199 W2 w2 = W2::Zero(); 200 strm2 >> w2; 201 202 w = PairWeight<W1, W2>(w1, w2); 203 return strm; 204 } 205 206 private: 207 W1 value1_; 208 W2 value2_; 209 210 }; 211 212 template <class W1, class W2> 213 inline bool operator==(const PairWeight<W1, W2> &w, 214 const PairWeight<W1, W2> &v) { 215 return w.Value1() == v.Value1() && w.Value2() == v.Value2(); 216 } 217 218 template <class W1, class W2> 219 inline bool operator!=(const PairWeight<W1, W2> &w1, 220 const PairWeight<W1, W2> &w2) { 221 return w1.Value1() != w2.Value1() || w1.Value2() != w2.Value2(); 222 } 223 224 225 template <class W1, class W2> 226 inline bool ApproxEqual(const PairWeight<W1, W2> &w1, 227 const PairWeight<W1, W2> &w2, 228 float delta = kDelta) { 229 return ApproxEqual(w1.Value1(), w2.Value1(), delta) && 230 ApproxEqual(w1.Value2(), w2.Value2(), delta); 231 } 232 233 template <class W1, class W2> 234 inline ostream &operator<<(ostream &strm, const PairWeight<W1, W2> &w) { 235 if(FLAGS_fst_weight_separator.size() != 1) { 236 FSTERROR() << "FLAGS_fst_weight_separator.size() is not equal to 1"; 237 strm.clear(std::ios::badbit); 238 return strm; 239 } 240 char separator = FLAGS_fst_weight_separator[0]; 241 if (FLAGS_fst_weight_parentheses.empty()) 242 return strm << w.Value1() << separator << w.Value2(); 243 244 if (FLAGS_fst_weight_parentheses.size() != 2) { 245 FSTERROR() << "FLAGS_fst_weight_parentheses.size() is not equal to 2"; 246 strm.clear(std::ios::badbit); 247 return strm; 248 } 249 char open_paren = FLAGS_fst_weight_parentheses[0]; 250 char close_paren = FLAGS_fst_weight_parentheses[1]; 251 return strm << open_paren << w.Value1() << separator 252 << w.Value2() << close_paren ; 253 } 254 255 template <class W1, class W2> 256 inline istream &operator>>(istream &strm, PairWeight<W1, W2> &w) { 257 if(FLAGS_fst_weight_separator.size() != 1) { 258 FSTERROR() << "FLAGS_fst_weight_separator.size() is not equal to 1"; 259 strm.clear(std::ios::badbit); 260 return strm; 261 } 262 char separator = FLAGS_fst_weight_separator[0]; 263 bool read_parens = !FLAGS_fst_weight_parentheses.empty(); 264 if (read_parens) { 265 if (FLAGS_fst_weight_parentheses.size() != 2) { 266 FSTERROR() << "FLAGS_fst_weight_parentheses.size() is not equal to 2"; 267 strm.clear(std::ios::badbit); 268 return strm; 269 } 270 return PairWeight<W1, W2>::ReadWithParen( 271 strm, w, separator, FLAGS_fst_weight_parentheses[0], 272 FLAGS_fst_weight_parentheses[1]); 273 } else { 274 return PairWeight<W1, W2>::ReadNoParen(strm, w, separator); 275 } 276 } 277 278 } // namespace fst 279 280 #endif // FST_LIB_PAIR_WEIGHT_H_ 281