14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// product-weight.h
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Licensed under the Apache License, Version 2.0 (the "License");
44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// you may not use this file except in compliance with the License.
54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// You may obtain a copy of the License at
64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//      http://www.apache.org/licenses/LICENSE-2.0
84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Unless required by applicable law or agreed to in writing, software
104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// distributed under the License is distributed on an "AS IS" BASIS,
114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// See the License for the specific language governing permissions and
134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// limitations under the License.
144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// \file
174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Product weight set and associated semiring operation definitions.
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifndef FST_LIB_PRODUCT_WEIGHT_H__
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define FST_LIB_PRODUCT_WEIGHT_H__
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/weight.h"
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectDECLARE_string(fst_product_separator);
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectnamespace fst {
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Product semiring: W1 * W2
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate<class W1, class W2>
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass ProductWeight {
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project public:
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef ProductWeight<typename W1::ReverseWeight, typename W2::ReverseWeight>
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ReverseWeight;
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ProductWeight() {}
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ProductWeight(W1 w1, W2 w2) : value1_(w1), value2_(w2) {}
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static const ProductWeight<W1, W2> &Zero() {
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    static const ProductWeight<W1, W2> zero(W1::Zero(), W2::Zero());
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return zero;
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static const ProductWeight<W1, W2> &One() {
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    static const ProductWeight<W1, W2> one(W1::One(), W2::One());
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return one;
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static const string &Type() {
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    static const string type = W1::Type() + "_X_" + W2::Type();
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return type;
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  istream &Read(istream &strm) {
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    value1_.Read(strm);
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return value2_.Read(strm);
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ostream &Write(ostream &strm) const {
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    value1_.Write(strm);
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return value2_.Write(strm);
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ProductWeight<W1, W2> &operator=(const ProductWeight<W1, W2> &w) {
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    value1_ = w.Value1();
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    value2_ = w.Value2();
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return *this;
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bool Member() const { return value1_.Member() && value2_.Member(); }
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ssize_t Hash() const {
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ssize_t h1 = value1_.Hash();
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ssize_t h2 = value2_.Hash();
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    int lshift = 5;
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    int rshift = sizeof(ssize_t) - 5;
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return h1 << lshift ^ h1 >> rshift ^ h2;
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ProductWeight<W1, W2> Quantize(float delta = kDelta) const {
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ProductWeight<W1, W2>(value1_.Quantize(), value2_.Quantize());
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ReverseWeight Reverse() const {
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ReverseWeight(value1_.Reverse(), value2_.Reverse());
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static uint64 Properties() {
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    uint64 props1 = W1::Properties();
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    uint64 props2 = W2::Properties();
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return props1 & props2 & (kLeftSemiring | kRightSemiring |
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                              kCommutative | kIdempotent);
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  W1 Value1() const { return value1_; }
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  W2 Value2() const { return value2_; }
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project private:
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  W1 value1_;
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  W2 value2_;
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class W1, class W2>
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline bool operator==(const ProductWeight<W1, W2> &w,
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                       const ProductWeight<W1, W2> &v) {
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return w.Value1() == v.Value1() && w.Value2() == v.Value2();
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class W1, class W2>
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline bool operator!=(const ProductWeight<W1, W2> &w1,
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                       const ProductWeight<W1, W2> &w2) {
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return w1.Value1() != w2.Value1() || w1.Value2() != w2.Value2();
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class W1, class W2>
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline bool ApproxEqual(const ProductWeight<W1, W2> &w1,
1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                        const ProductWeight<W1, W2> &w2,
1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                        float delta = kDelta) {
1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return w1 == w2;
1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class W1, class W2>
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline ostream &operator<<(ostream &strm, const ProductWeight<W1, W2> &w) {
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  CHECK(FLAGS_fst_product_separator.size() == 1);
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char separator = FLAGS_fst_product_separator[0];
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return strm << w.Value1() << separator << w.Value2();
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class W1, class W2>
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline istream &operator>>(istream &strm, ProductWeight<W1, W2> &w) {
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  CHECK(FLAGS_fst_product_separator.size() == 1);
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char separator = FLAGS_fst_product_separator[0];
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int c;
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // read any initial whitespapce
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  while (true) {
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    c = strm.get();
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (c == EOF || c == separator) {
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      strm.clear(std::ios::badbit);
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return strm;
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!isspace(c))
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      break;
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // read first element
1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  string s1;
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  do {
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    s1 += c;
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    c = strm.get();
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (c == EOF || isspace(c)) {
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      strm.clear(std::ios::badbit);
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return strm;
1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  } while (c != separator);
1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  istringstream strm1(s1);
1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  W1 w1 = W1::Zero();
1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strm1 >> w1;
1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // read second element
1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  W2 w2 = W2::Zero();
1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strm >> w2;
1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  w = ProductWeight<W1, W2>(w1, w2);
1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return strm;
1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class W1, class W2>
1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline ProductWeight<W1, W2> Plus(const ProductWeight<W1, W2> &w,
1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                  const ProductWeight<W1, W2> &v) {
1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ProductWeight<W1, W2>(Plus(w.Value1(), v.Value1()),
1744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                               Plus(w.Value2(), v.Value2()));
1754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class W1, class W2>
1784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline ProductWeight<W1, W2> Times(const ProductWeight<W1, W2> &w,
1794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                   const ProductWeight<W1, W2> &v) {
1804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ProductWeight<W1, W2>(Times(w.Value1(), v.Value1()),
1814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                               Times(w.Value2(), v.Value2()));
1824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class W1, class W2>
1854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline ProductWeight<W1, W2> Divide(const ProductWeight<W1, W2> &w,
1864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                    const ProductWeight<W1, W2> &v,
1874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                    DivideType typ = DIVIDE_ANY) {
1884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ProductWeight<W1, W2>(Divide(w.Value1(), v.Value1(), typ),
1894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                               Divide(w.Value2(), v.Value2(), typ));
1904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}  // namespace fst;
1934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif  // FST_LIB_PRODUCT_WEIGHT_H__
195