| // tuple-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: allauzen@google (Cyril Allauzen) |
| // |
| // \file |
| // Tuple weight set operation definitions. |
| |
| #ifndef FST_LIB_TUPLE_WEIGHT_H__ |
| #define FST_LIB_TUPLE_WEIGHT_H__ |
| |
| #include <string> |
| #include <vector> |
| using std::vector; |
| |
| #include <fst/weight.h> |
| |
| |
| DECLARE_string(fst_weight_parentheses); |
| DECLARE_string(fst_weight_separator); |
| |
| namespace fst { |
| |
| template<class W, unsigned int n> class TupleWeight; |
| template <class W, unsigned int n> |
| istream &operator>>(istream &strm, TupleWeight<W, n> &w); |
| |
| // n-tuple weight, element of the n-th catersian power of W |
| template <class W, unsigned int n> |
| class TupleWeight { |
| public: |
| typedef TupleWeight<typename W::ReverseWeight, n> ReverseWeight; |
| |
| TupleWeight() {} |
| |
| TupleWeight(const TupleWeight &w) { |
| for (size_t i = 0; i < n; ++i) |
| values_[i] = w.values_[i]; |
| } |
| |
| template <class Iterator> |
| TupleWeight(Iterator begin, Iterator end) { |
| for (Iterator iter = begin; iter != end; ++iter) |
| values_[iter - begin] = *iter; |
| } |
| |
| TupleWeight(const W &w) { |
| for (size_t i = 0; i < n; ++i) |
| values_[i] = w; |
| } |
| |
| static const TupleWeight<W, n> &Zero() { |
| static const TupleWeight<W, n> zero(W::Zero()); |
| return zero; |
| } |
| |
| static const TupleWeight<W, n> &One() { |
| static const TupleWeight<W, n> one(W::One()); |
| return one; |
| } |
| |
| static const TupleWeight<W, n> &NoWeight() { |
| static const TupleWeight<W, n> no_weight(W::NoWeight()); |
| return no_weight; |
| } |
| |
| static unsigned int Length() { |
| return n; |
| } |
| |
| istream &Read(istream &strm) { |
| for (size_t i = 0; i < n; ++i) |
| values_[i].Read(strm); |
| return strm; |
| } |
| |
| ostream &Write(ostream &strm) const { |
| for (size_t i = 0; i < n; ++i) |
| values_[i].Write(strm); |
| return strm; |
| } |
| |
| TupleWeight<W, n> &operator=(const TupleWeight<W, n> &w) { |
| for (size_t i = 0; i < n; ++i) |
| values_[i] = w.values_[i]; |
| return *this; |
| } |
| |
| bool Member() const { |
| bool member = true; |
| for (size_t i = 0; i < n; ++i) |
| member = member && values_[i].Member(); |
| return member; |
| } |
| |
| size_t Hash() const { |
| uint64 hash = 0; |
| for (size_t i = 0; i < n; ++i) |
| hash = 5 * hash + values_[i].Hash(); |
| return size_t(hash); |
| } |
| |
| TupleWeight<W, n> Quantize(float delta = kDelta) const { |
| TupleWeight<W, n> w; |
| for (size_t i = 0; i < n; ++i) |
| w.values_[i] = values_[i].Quantize(delta); |
| return w; |
| } |
| |
| ReverseWeight Reverse() const { |
| TupleWeight<W, n> w; |
| for (size_t i = 0; i < n; ++i) |
| w.values_[i] = values_[i].Reverse(); |
| return w; |
| } |
| |
| const W& Value(size_t i) const { return values_[i]; } |
| |
| void SetValue(size_t i, const W &w) { values_[i] = w; } |
| |
| protected: |
| // Reads TupleWeight when there are no parentheses around tuple terms |
| inline static istream &ReadNoParen(istream &strm, |
| TupleWeight<W, n> &w, |
| char separator) { |
| int c; |
| do { |
| c = strm.get(); |
| } while (isspace(c)); |
| |
| for (size_t i = 0; i < n - 1; ++i) { |
| string s; |
| if (i) |
| c = strm.get(); |
| while (c != separator) { |
| if (c == EOF) { |
| strm.clear(std::ios::badbit); |
| return strm; |
| } |
| s += c; |
| c = strm.get(); |
| } |
| // read (i+1)-th element |
| istringstream sstrm(s); |
| W r = W::Zero(); |
| sstrm >> r; |
| w.SetValue(i, r); |
| } |
| |
| // read n-th element |
| W r = W::Zero(); |
| strm >> r; |
| w.SetValue(n - 1, r); |
| |
| return strm; |
| } |
| |
| // Reads TupleWeight when there are parentheses around tuple terms |
| inline static istream &ReadWithParen(istream &strm, |
| TupleWeight<W, n> &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::badbit); |
| return strm; |
| } |
| |
| for (size_t i = 0; i < n - 1; ++i) { |
| // read (i+1)-th element |
| stack<int> parens; |
| string s; |
| c = strm.get(); |
| while (c != separator || !parens.empty()) { |
| if (c == EOF) { |
| strm.clear(std::ios::badbit); |
| return strm; |
| } |
| s += 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 sstrm(s); |
| W r = W::Zero(); |
| sstrm >> r; |
| w.SetValue(i, r); |
| } |
| |
| // read n-th element |
| string s; |
| c = strm.get(); |
| while (c != EOF) { |
| s += c; |
| c = strm.get(); |
| } |
| if (s.empty() || *s.rbegin() != close_paren) { |
| FSTERROR() << " is fst_weight_parentheses flag set correcty? "; |
| strm.clear(std::ios::failbit); |
| return strm; |
| } |
| s.erase(s.size() - 1, 1); |
| istringstream sstrm(s); |
| W r = W::Zero(); |
| sstrm >> r; |
| w.SetValue(n - 1, r); |
| |
| return strm; |
| } |
| |
| |
| private: |
| W values_[n]; |
| |
| friend istream &operator>><W, n>(istream&, TupleWeight<W, n>&); |
| }; |
| |
| template <class W, unsigned int n> |
| inline bool operator==(const TupleWeight<W, n> &w1, |
| const TupleWeight<W, n> &w2) { |
| bool equal = true; |
| for (size_t i = 0; i < n; ++i) |
| equal = equal && (w1.Value(i) == w2.Value(i)); |
| return equal; |
| } |
| |
| template <class W, unsigned int n> |
| inline bool operator!=(const TupleWeight<W, n> &w1, |
| const TupleWeight<W, n> &w2) { |
| bool not_equal = false; |
| for (size_t i = 0; (i < n) && !not_equal; ++i) |
| not_equal = not_equal || (w1.Value(i) != w2.Value(i)); |
| return not_equal; |
| } |
| |
| template <class W, unsigned int n> |
| inline bool ApproxEqual(const TupleWeight<W, n> &w1, |
| const TupleWeight<W, n> &w2, |
| float delta = kDelta) { |
| bool approx_equal = true; |
| for (size_t i = 0; i < n; ++i) |
| approx_equal = approx_equal && |
| ApproxEqual(w1.Value(i), w2.Value(i), delta); |
| return approx_equal; |
| } |
| |
| template <class W, unsigned int n> |
| inline ostream &operator<<(ostream &strm, const TupleWeight<W, n> &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 write_parens = false; |
| if (!FLAGS_fst_weight_parentheses.empty()) { |
| 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; |
| } |
| write_parens = true; |
| } |
| |
| if (write_parens) |
| strm << FLAGS_fst_weight_parentheses[0]; |
| for (size_t i = 0; i < n; ++i) { |
| if(i) |
| strm << separator; |
| strm << w.Value(i); |
| } |
| if (write_parens) |
| strm << FLAGS_fst_weight_parentheses[1]; |
| |
| return strm; |
| } |
| |
| template <class W, unsigned int n> |
| inline istream &operator>>(istream &strm, TupleWeight<W, n> &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()) { |
| 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 TupleWeight<W, n>::ReadWithParen( |
| strm, w, separator, FLAGS_fst_weight_parentheses[0], |
| FLAGS_fst_weight_parentheses[1]); |
| } else { |
| return TupleWeight<W, n>::ReadNoParen(strm, w, separator); |
| } |
| } |
| |
| |
| |
| } // namespace fst |
| |
| #endif // FST_LIB_TUPLE_WEIGHT_H__ |