| // pair-weight.h |
| |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| // Copyright 2005-2010 Google, Inc. |
| // Author: shumash@google.com (Masha Maria Shugrina) |
| // |
| // \file |
| // Pair weight templated base class for weight classes that |
| // contain two weights (e.g. Product, Lexicographic) |
| |
| #ifndef FST_LIB_PAIR_WEIGHT_H_ |
| #define FST_LIB_PAIR_WEIGHT_H_ |
| |
| #include <climits> |
| #include <stack> |
| #include <string> |
| |
| #include <fst/weight.h> |
| |
| |
| DECLARE_string(fst_weight_parentheses); |
| DECLARE_string(fst_weight_separator); |
| |
| namespace fst { |
| |
| template<class W1, class W2> class PairWeight; |
| template <class W1, class W2> |
| istream &operator>>(istream &strm, PairWeight<W1, W2> &w); |
| |
| template<class W1, class W2> |
| class PairWeight { |
| public: |
| friend istream &operator>><W1, W2>(istream&, PairWeight<W1, W2>&); |
| |
| typedef PairWeight<typename W1::ReverseWeight, |
| typename W2::ReverseWeight> |
| ReverseWeight; |
| |
| PairWeight() {} |
| |
| PairWeight(const PairWeight& w) : value1_(w.value1_), value2_(w.value2_) {} |
| |
| PairWeight(W1 w1, W2 w2) : value1_(w1), value2_(w2) {} |
| |
| static const PairWeight<W1, W2> &Zero() { |
| static const PairWeight<W1, W2> zero(W1::Zero(), W2::Zero()); |
| return zero; |
| } |
| |
| static const PairWeight<W1, W2> &One() { |
| static const PairWeight<W1, W2> one(W1::One(), W2::One()); |
| return one; |
| } |
| |
| static const PairWeight<W1, W2> &NoWeight() { |
| static const PairWeight<W1, W2> no_weight(W1::NoWeight(), W2::NoWeight()); |
| return no_weight; |
| } |
| |
| istream &Read(istream &strm) { |
| value1_.Read(strm); |
| return value2_.Read(strm); |
| } |
| |
| ostream &Write(ostream &strm) const { |
| value1_.Write(strm); |
| return value2_.Write(strm); |
| } |
| |
| PairWeight<W1, W2> &operator=(const PairWeight<W1, W2> &w) { |
| value1_ = w.Value1(); |
| value2_ = w.Value2(); |
| return *this; |
| } |
| |
| bool Member() const { return value1_.Member() && value2_.Member(); } |
| |
| size_t Hash() const { |
| size_t h1 = value1_.Hash(); |
| size_t h2 = value2_.Hash(); |
| const int lshift = 5; |
| const int rshift = CHAR_BIT * sizeof(size_t) - 5; |
| return h1 << lshift ^ h1 >> rshift ^ h2; |
| } |
| |
| PairWeight<W1, W2> Quantize(float delta = kDelta) const { |
| return PairWeight<W1, W2>(value1_.Quantize(delta), |
| value2_.Quantize(delta)); |
| } |
| |
| ReverseWeight Reverse() const { |
| return ReverseWeight(value1_.Reverse(), value2_.Reverse()); |
| } |
| |
| const W1& Value1() const { return value1_; } |
| |
| const W2& Value2() const { return value2_; } |
| |
| protected: |
| void SetValue1(const W1 &w) { value1_ = w; } |
| void SetValue2(const W2 &w) { value2_ = w; } |
| |
| // Reads PairWeight when there are not parentheses around pair terms |
| inline static istream &ReadNoParen( |
| istream &strm, PairWeight<W1, W2>& w, char separator) { |
| int c; |
| do { |
| c = strm.get(); |
| } while (isspace(c)); |
| |
| string s1; |
| while (c != separator) { |
| if (c == EOF) { |
| strm.clear(std::ios::badbit); |
| return strm; |
| } |
| s1 += c; |
| c = strm.get(); |
| } |
| istringstream strm1(s1); |
| W1 w1 = W1::Zero(); |
| strm1 >> w1; |
| |
| // read second element |
| W2 w2 = W2::Zero(); |
| strm >> w2; |
| |
| w = PairWeight<W1, W2>(w1, w2); |
| return strm; |
| } |
| |
| // Reads PairWeight when there are parentheses around pair terms |
| inline static istream &ReadWithParen( |
| istream &strm, PairWeight<W1, W2>& w, |
| char separator, char open_paren, char close_paren) { |
| int c; |
| do { |
| c = strm.get(); |
| } while (isspace(c)); |
| if (c != open_paren) { |
| FSTERROR() << " is fst_weight_parentheses flag set correcty? "; |
| strm.clear(std::ios::failbit); |
| return strm; |
| } |
| c = strm.get(); |
| |
| // read first element |
| stack<int> parens; |
| string s1; |
| while (c != separator || !parens.empty()) { |
| if (c == EOF) { |
| strm.clear(std::ios::badbit); |
| return strm; |
| } |
| s1 += c; |
| // if parens encountered before separator, they must be matched |
| if (c == open_paren) { |
| parens.push(1); |
| } else if (c == close_paren) { |
| // Fail for mismatched parens |
| if (parens.empty()) { |
| strm.clear(std::ios::failbit); |
| return strm; |
| } |
| parens.pop(); |
| } |
| c = strm.get(); |
| } |
| istringstream strm1(s1); |
| W1 w1 = W1::Zero(); |
| strm1 >> w1; |
| |
| // read second element |
| string s2; |
| c = strm.get(); |
| while (c != EOF) { |
| s2 += c; |
| c = strm.get(); |
| } |
| if (s2.empty() || (s2[s2.size() - 1] != close_paren)) { |
| FSTERROR() << " is fst_weight_parentheses flag set correcty? "; |
| strm.clear(std::ios::failbit); |
| return strm; |
| } |
| |
| s2.erase(s2.size() - 1, 1); |
| istringstream strm2(s2); |
| W2 w2 = W2::Zero(); |
| strm2 >> w2; |
| |
| w = PairWeight<W1, W2>(w1, w2); |
| return strm; |
| } |
| |
| private: |
| W1 value1_; |
| W2 value2_; |
| |
| }; |
| |
| template <class W1, class W2> |
| inline bool operator==(const PairWeight<W1, W2> &w, |
| const PairWeight<W1, W2> &v) { |
| return w.Value1() == v.Value1() && w.Value2() == v.Value2(); |
| } |
| |
| template <class W1, class W2> |
| inline bool operator!=(const PairWeight<W1, W2> &w1, |
| const PairWeight<W1, W2> &w2) { |
| return w1.Value1() != w2.Value1() || w1.Value2() != w2.Value2(); |
| } |
| |
| |
| template <class W1, class W2> |
| inline bool ApproxEqual(const PairWeight<W1, W2> &w1, |
| const PairWeight<W1, W2> &w2, |
| float delta = kDelta) { |
| return ApproxEqual(w1.Value1(), w2.Value1(), delta) && |
| ApproxEqual(w1.Value2(), w2.Value2(), delta); |
| } |
| |
| template <class W1, class W2> |
| inline ostream &operator<<(ostream &strm, const PairWeight<W1, W2> &w) { |
| if(FLAGS_fst_weight_separator.size() != 1) { |
| FSTERROR() << "FLAGS_fst_weight_separator.size() is not equal to 1"; |
| strm.clear(std::ios::badbit); |
| return strm; |
| } |
| char separator = FLAGS_fst_weight_separator[0]; |
| if (FLAGS_fst_weight_parentheses.empty()) |
| return strm << w.Value1() << separator << w.Value2(); |
| |
| if (FLAGS_fst_weight_parentheses.size() != 2) { |
| FSTERROR() << "FLAGS_fst_weight_parentheses.size() is not equal to 2"; |
| strm.clear(std::ios::badbit); |
| return strm; |
| } |
| char open_paren = FLAGS_fst_weight_parentheses[0]; |
| char close_paren = FLAGS_fst_weight_parentheses[1]; |
| return strm << open_paren << w.Value1() << separator |
| << w.Value2() << close_paren ; |
| } |
| |
| template <class W1, class W2> |
| inline istream &operator>>(istream &strm, PairWeight<W1, W2> &w) { |
| if(FLAGS_fst_weight_separator.size() != 1) { |
| FSTERROR() << "FLAGS_fst_weight_separator.size() is not equal to 1"; |
| strm.clear(std::ios::badbit); |
| return strm; |
| } |
| char separator = FLAGS_fst_weight_separator[0]; |
| bool read_parens = !FLAGS_fst_weight_parentheses.empty(); |
| if (read_parens) { |
| if (FLAGS_fst_weight_parentheses.size() != 2) { |
| FSTERROR() << "FLAGS_fst_weight_parentheses.size() is not equal to 2"; |
| strm.clear(std::ios::badbit); |
| return strm; |
| } |
| return PairWeight<W1, W2>::ReadWithParen( |
| strm, w, separator, FLAGS_fst_weight_parentheses[0], |
| FLAGS_fst_weight_parentheses[1]); |
| } else { |
| return PairWeight<W1, W2>::ReadNoParen(strm, w, separator); |
| } |
| } |
| |
| } // namespace fst |
| |
| #endif // FST_LIB_PAIR_WEIGHT_H_ |