14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// float-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// Float weight set and associated semiring operation definitions.
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifndef FST_LIB_FLOAT_WEIGHT_H__
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define FST_LIB_FLOAT_WEIGHT_H__
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <limits>
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/weight.h"
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectnamespace fst {
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic const float kPosInfinity = numeric_limits<float>::infinity();
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic const float kNegInfinity = -kPosInfinity;
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Single precision floating point weight base class
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass FloatWeight {
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project public:
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FloatWeight() {}
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FloatWeight(float f) : value_(f) {}
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FloatWeight(const FloatWeight &w) : value_(w.value_) {}
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FloatWeight &operator=(const FloatWeight &w) {
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    value_ = w.value_;
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return *this;
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  istream &Read(istream &strm) {
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ReadType(strm, &value_);
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ostream &Write(ostream &strm) const {
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return WriteType(strm, value_);
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ssize_t Hash() const {
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    union {
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      float f;
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ssize_t s;
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    } u = { value_ };
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return u.s;
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  const float &Value() const { return value_; }
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project protected:
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  float value_;
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline bool operator==(const FloatWeight &w1, const FloatWeight &w2) {
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Volatile qualifier thwarts over-aggressive compiler optimizations
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // that lead to problems esp. with NaturalLess().
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  volatile float v1 = w1.Value();
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  volatile float v2 = w2.Value();
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return v1 == v2;
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline bool operator!=(const FloatWeight &w1, const FloatWeight &w2) {
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return !(w1 == w2);
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline bool ApproxEqual(const FloatWeight &w1, const FloatWeight &w2,
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                        float delta = kDelta) {
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return w1.Value() <= w2.Value() + delta && w2.Value() <= w1.Value() + delta;
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline ostream &operator<<(ostream &strm, const FloatWeight &w) {
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (w.Value() == kPosInfinity)
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return strm << "Infinity";
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (w.Value() == kNegInfinity)
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return strm << "-Infinity";
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (w.Value() != w.Value())   // Fails for NaN
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return strm << "BadFloat";
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return strm << w.Value();
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline istream &operator>>(istream &strm, FloatWeight &w) {
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  string s;
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strm >> s;
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (s == "Infinity") {
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    w = FloatWeight(kPosInfinity);
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  } else if (s == "-Infinity") {
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    w = FloatWeight(kNegInfinity);
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  } else {
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    char *p;
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    float f = strtod(s.c_str(), &p);
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (p < s.c_str() + s.size())
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      strm.clear(std::ios::badbit);
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      w = FloatWeight(f);
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return strm;
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Tropical semiring: (min, +, inf, 0)
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass TropicalWeight : public FloatWeight {
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project public:
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef TropicalWeight ReverseWeight;
1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  TropicalWeight() : FloatWeight() {}
1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  TropicalWeight(float f) : FloatWeight(f) {}
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  TropicalWeight(const TropicalWeight &w) : FloatWeight(w) {}
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static const TropicalWeight Zero() { return TropicalWeight(kPosInfinity); }
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static const TropicalWeight One() { return TropicalWeight(0.0F); }
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static const string &Type() {
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    static const string type = "tropical";
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return type;
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bool Member() const {
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // First part fails for IEEE NaN
1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return Value() == Value() && Value() != kNegInfinity;
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  TropicalWeight Quantize(float delta = kDelta) const {
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return TropicalWeight(floor(Value()/delta + 0.5F) * delta);
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  TropicalWeight Reverse() const { return *this; }
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static uint64 Properties() {
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return kLeftSemiring | kRightSemiring | kCommutative |
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      kPath | kIdempotent;
1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline TropicalWeight Plus(const TropicalWeight &w1,
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                           const TropicalWeight &w2) {
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return w1.Value() < w2.Value() ? w1 : w2;
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline TropicalWeight Times(const TropicalWeight &w1,
1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                            const TropicalWeight &w2) {
1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  float f1 = w1.Value(), f2 = w2.Value();
1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (f1 == kPosInfinity)
1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return w1;
1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (f2 == kPosInfinity)
1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return w2;
1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return TropicalWeight(f1 + f2);
1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline TropicalWeight Divide(const TropicalWeight &w1,
1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                             const TropicalWeight &w2,
1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                             DivideType typ = DIVIDE_ANY) {
1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  float f1 = w1.Value(), f2 = w2.Value();
1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (f2 == kPosInfinity)
1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return kNegInfinity;
1744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (f1 == kPosInfinity)
1754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return kPosInfinity;
1764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
1774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return TropicalWeight(f1 - f2);
1784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Log semiring: (log(e^-x + e^y), +, inf, 0)
1824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass LogWeight : public FloatWeight {
1834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project public:
1844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef LogWeight ReverseWeight;
1854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  LogWeight() : FloatWeight() {}
1874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  LogWeight(float f) : FloatWeight(f) {}
1894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  LogWeight(const LogWeight &w) : FloatWeight(w) {}
1914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static const LogWeight Zero() {   return LogWeight(kPosInfinity); }
1934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static const LogWeight One() { return LogWeight(0.0F); }
1954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static const string &Type() {
1974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    static const string type = "log";
1984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return type;
1994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bool Member() const {
2024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    // First part fails for IEEE NaN
2034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return Value() == Value() && Value() != kNegInfinity;
2044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  LogWeight Quantize(float delta = kDelta) const {
2074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return LogWeight(floor(Value()/delta + 0.5F) * delta);
2084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  LogWeight Reverse() const { return *this; }
2114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static uint64 Properties() {
2134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return kLeftSemiring | kRightSemiring | kCommutative;
2144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
2164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline double LogExp(double x) { return log(1.0F + exp(-x)); }
2184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline LogWeight Plus(const LogWeight &w1, const LogWeight &w2) {
2204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  float f1 = w1.Value(), f2 = w2.Value();
2214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (f1 == kPosInfinity)
2224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return w2;
2234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (f2 == kPosInfinity)
2244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return w1;
2254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (f1 > f2)
2264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return LogWeight(f2 - LogExp(f1 - f2));
2274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
2284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return LogWeight(f1 - LogExp(f2 - f1));
2294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline LogWeight Times(const LogWeight &w1, const LogWeight &w2) {
2324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  float f1 = w1.Value(), f2 = w2.Value();
2334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (f1 == kPosInfinity)
2344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return w1;
2354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (f2 == kPosInfinity)
2364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return w2;
2374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
2384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return LogWeight(f1 + f2);
2394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectinline LogWeight Divide(const LogWeight &w1,
2424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                             const LogWeight &w2,
2434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                             DivideType typ = DIVIDE_ANY) {
2444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  float f1 = w1.Value(), f2 = w2.Value();
2454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (f2 == kPosInfinity)
2464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return kNegInfinity;
2474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (f1 == kPosInfinity)
2484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return kPosInfinity;
2494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
2504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return LogWeight(f1 - f2);
2514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}  // namespace fst;
2544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif  // FST_LIB_FLOAT_WEIGHT_H__
256