00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef FST_LIB_PAIR_WEIGHT_H_
00023 #define FST_LIB_PAIR_WEIGHT_H_
00024
00025 #include <climits>
00026 #include <stack>
00027 #include <string>
00028 #include <fst/weight.h>
00029
00030 DECLARE_string(fst_weight_parentheses);
00031 DECLARE_string(fst_weight_separator);
00032
00033 namespace fst {
00034
00035 template<class W1, class W2> class PairWeight;
00036 template <class W1, class W2>
00037 istream &operator>>(istream &strm, PairWeight<W1, W2> &w);
00038
00039 template<class W1, class W2>
00040 class PairWeight {
00041 public:
00042 typedef PairWeight<typename W1::ReverseWeight,
00043 typename W2::ReverseWeight>
00044 ReverseWeight;
00045
00046 PairWeight() {}
00047
00048 PairWeight(const PairWeight& w) : value1_(w.value1_), value2_(w.value2_) {}
00049
00050 PairWeight(W1 w1, W2 w2) : value1_(w1), value2_(w2) {}
00051
00052 static const PairWeight<W1, W2> &Zero() {
00053 static const PairWeight<W1, W2> zero(W1::Zero(), W2::Zero());
00054 return zero;
00055 }
00056
00057 static const PairWeight<W1, W2> &One() {
00058 static const PairWeight<W1, W2> one(W1::One(), W2::One());
00059 return one;
00060 }
00061
00062 istream &Read(istream &strm) {
00063 value1_.Read(strm);
00064 return value2_.Read(strm);
00065 }
00066
00067 ostream &Write(ostream &strm) const {
00068 value1_.Write(strm);
00069 return value2_.Write(strm);
00070 }
00071
00072 PairWeight<W1, W2> &operator=(const PairWeight<W1, W2> &w) {
00073 value1_ = w.Value1();
00074 value2_ = w.Value2();
00075 return *this;
00076 }
00077
00078 bool Member() const { return value1_.Member() && value2_.Member(); }
00079
00080 size_t Hash() const {
00081 size_t h1 = value1_.Hash();
00082 size_t h2 = value2_.Hash();
00083 const int lshift = 5;
00084 const int rshift = CHAR_BIT * sizeof(size_t) - 5;
00085 return h1 << lshift ^ h1 >> rshift ^ h2;
00086 }
00087
00088 PairWeight<W1, W2> Quantize(float delta = kDelta) const {
00089 return PairWeight<W1, W2>(value1_.Quantize(delta),
00090 value2_.Quantize(delta));
00091 }
00092
00093 ReverseWeight Reverse() const {
00094 return ReverseWeight(value1_.Reverse(), value2_.Reverse());
00095 }
00096
00097 const W1& Value1() const { return value1_; }
00098
00099 const W2& Value2() const { return value2_; }
00100
00101 protected:
00102
00103 inline static istream &ReadNoParen(
00104 istream &strm, PairWeight<W1, W2>& w, char separator) {
00105 int c;
00106 do {
00107 c = strm.get();
00108 } while (isspace(c));
00109
00110 string s1;
00111 while (c != separator) {
00112 if (c == EOF) {
00113 strm.clear(std::ios::badbit);
00114 return strm;
00115 }
00116 s1 += c;
00117 c = strm.get();
00118 }
00119 istringstream strm1(s1);
00120 W1 w1 = W1::Zero();
00121 strm1 >> w1;
00122
00123
00124 W2 w2 = W2::Zero();
00125 strm >> w2;
00126
00127 w = PairWeight<W1, W2>(w1, w2);
00128 return strm;
00129 }
00130
00131
00132 inline static istream &ReadWithParen(
00133 istream &strm, PairWeight<W1, W2>& w,
00134 char separator, char open_paren, char close_paren) {
00135 int c;
00136 do {
00137 c = strm.get();
00138 } while (isspace(c));
00139 if (c != open_paren)
00140 LOG(FATAL) << " is fst_weight_parentheses flag set correcty? ";
00141 c = strm.get();
00142
00143
00144 stack<int> parens;
00145 string s1;
00146 while (c != separator || !parens.empty()) {
00147 if (c == EOF) {
00148 strm.clear(std::ios::badbit);
00149 return strm;
00150 }
00151 s1 += c;
00152
00153 if (c == open_paren) {
00154 parens.push(1);
00155 } else if (c == close_paren) {
00156
00157 if (parens.empty()) {
00158 strm.clear(std::ios::failbit);
00159 return strm;
00160 }
00161 parens.pop();
00162 }
00163 c = strm.get();
00164 }
00165 istringstream strm1(s1);
00166 W1 w1 = W1::Zero();
00167 strm1 >> w1;
00168
00169
00170 string s2;
00171 c = strm.get();
00172 while (c != EOF) {
00173 s2 += c;
00174 c = strm.get();
00175 }
00176 CHECK(s2.size() > 0);
00177 if (s2[s2.size() - 1] != close_paren)
00178 LOG(FATAL) << " is fst_weight_parentheses flag set correcty? ";
00179 s2.erase(s2.size() - 1, 1);
00180 istringstream strm2(s2);
00181 W2 w2 = W2::Zero();
00182 strm2 >> w2;
00183
00184 w = PairWeight<W1, W2>(w1, w2);
00185 return strm;
00186 }
00187
00188 W1 value1_;
00189 W2 value2_;
00190 friend istream &operator>><W1, W2>(istream&, PairWeight<W1, W2>&);
00191 };
00192
00193 template <class W1, class W2>
00194 inline bool operator==(const PairWeight<W1, W2> &w,
00195 const PairWeight<W1, W2> &v) {
00196 return w.Value1() == v.Value1() && w.Value2() == v.Value2();
00197 }
00198
00199 template <class W1, class W2>
00200 inline bool operator!=(const PairWeight<W1, W2> &w1,
00201 const PairWeight<W1, W2> &w2) {
00202 return w1.Value1() != w2.Value1() || w1.Value2() != w2.Value2();
00203 }
00204
00205
00206 template <class W1, class W2>
00207 inline bool ApproxEqual(const PairWeight<W1, W2> &w1,
00208 const PairWeight<W1, W2> &w2,
00209 float delta = kDelta) {
00210 return ApproxEqual(w1.Value1(), w2.Value1(), delta) &&
00211 ApproxEqual(w1.Value2(), w2.Value2(), delta);
00212 }
00213
00214 template <class W1, class W2>
00215 inline ostream &operator<<(ostream &strm, const PairWeight<W1, W2> &w) {
00216 CHECK(FLAGS_fst_weight_separator.size() == 1);
00217 char separator = FLAGS_fst_weight_separator[0];
00218 if (FLAGS_fst_weight_parentheses.empty())
00219 return strm << w.Value1() << separator << w.Value2();
00220
00221 CHECK(FLAGS_fst_weight_parentheses.size() == 2);
00222 char open_paren = FLAGS_fst_weight_parentheses[0];
00223 char close_paren = FLAGS_fst_weight_parentheses[1];
00224 return strm << open_paren << w.Value1() << separator
00225 << w.Value2() << close_paren ;
00226 }
00227
00228 template <class W1, class W2>
00229 inline istream &operator>>(istream &strm, PairWeight<W1, W2> &w) {
00230 CHECK(FLAGS_fst_weight_separator.size() == 1);
00231 char separator = FLAGS_fst_weight_separator[0];
00232 bool read_parens = !FLAGS_fst_weight_parentheses.empty();
00233 if (read_parens) {
00234 CHECK(FLAGS_fst_weight_parentheses.size() == 2);
00235 return PairWeight<W1, W2>::ReadWithParen(
00236 strm, w, separator, FLAGS_fst_weight_parentheses[0],
00237 FLAGS_fst_weight_parentheses[1]);
00238 } else {
00239 return PairWeight<W1, W2>::ReadNoParen(strm, w, separator);
00240 }
00241 }
00242
00243 }
00244
00245 #endif /// FST_LIB_PAIR_WEIGHT_H_
00246