1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// float-weight.h
2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License");
4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License.
5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at
6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     http://www.apache.org/licenses/LICENSE-2.0
8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software
10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS,
11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and
13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License.
14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc.
16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: riley@google.com (Michael Riley)
17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// \file
19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Float weight set and associated semiring operation definitions.
20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_LIB_FLOAT_WEIGHT_H__
23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_LIB_FLOAT_WEIGHT_H__
24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <limits>
26f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <climits>
27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <sstream>
28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <string>
29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/util.h>
31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/weight.h>
32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst {
35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// numeric limits class
37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass FloatLimits {
39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const T kPosInfinity;
41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const T kNegInfinity;
42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const T kNumberBad;
43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonconst T FloatLimits<T>::kPosInfinity = numeric_limits<T>::infinity();
47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonconst T FloatLimits<T>::kNegInfinity = -FloatLimits<T>::kPosInfinity;
50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonconst T FloatLimits<T>::kNumberBad = numeric_limits<T>::quiet_NaN();
53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// weight class to be templated on floating-points types
55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T = float>
56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass FloatWeightTpl {
57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  FloatWeightTpl() {}
59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  FloatWeightTpl(T f) : value_(f) {}
61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  FloatWeightTpl(const FloatWeightTpl<T> &w) : value_(w.value_) {}
63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  FloatWeightTpl<T> &operator=(const FloatWeightTpl<T> &w) {
65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    value_ = w.value_;
66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return *this;
67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  istream &Read(istream &strm) {
70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return ReadType(strm, &value_);
71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ostream &Write(ostream &strm) const {
74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return WriteType(strm, value_);
75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  size_t Hash() const {
78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    union {
79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      T f;
80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      size_t s;
81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } u;
82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    u.s = 0;
83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    u.f = value_;
84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return u.s;
85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const T &Value() const { return value_; }
88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson protected:
90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void SetValue(const T &f) { value_ = f; }
91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
92f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  inline static string GetPrecisionString() {
93f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    int64 size = sizeof(T);
94f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (size == sizeof(float)) return "";
95f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    size *= CHAR_BIT;
96f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    string result;
98f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Int64ToStr(size, &result);
99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return result;
100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T value_;
104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Single-precision float weight
107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef FloatWeightTpl<float> FloatWeight;
108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool operator==(const FloatWeightTpl<T> &w1,
111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       const FloatWeightTpl<T> &w2) {
112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Volatile qualifier thwarts over-aggressive compiler optimizations
113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // that lead to problems esp. with NaturalLess().
114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  volatile T v1 = w1.Value();
115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  volatile T v2 = w2.Value();
116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return v1 == v2;
117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
118f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool operator==(const FloatWeightTpl<double> &w1,
120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       const FloatWeightTpl<double> &w2) {
121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return operator==<double>(w1, w2);
122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool operator==(const FloatWeightTpl<float> &w1,
125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       const FloatWeightTpl<float> &w2) {
126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return operator==<float>(w1, w2);
127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool operator!=(const FloatWeightTpl<T> &w1,
131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       const FloatWeightTpl<T> &w2) {
132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return !(w1 == w2);
133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool operator!=(const FloatWeightTpl<double> &w1,
136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       const FloatWeightTpl<double> &w2) {
137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return operator!=<double>(w1, w2);
138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool operator!=(const FloatWeightTpl<float> &w1,
141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       const FloatWeightTpl<float> &w2) {
142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return operator!=<float>(w1, w2);
143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool ApproxEqual(const FloatWeightTpl<T> &w1,
147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                        const FloatWeightTpl<T> &w2,
148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                        float delta = kDelta) {
149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return w1.Value() <= w2.Value() + delta && w2.Value() <= w1.Value() + delta;
150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline ostream &operator<<(ostream &strm, const FloatWeightTpl<T> &w) {
154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (w.Value() == FloatLimits<T>::kPosInfinity)
155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return strm << "Infinity";
156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (w.Value() == FloatLimits<T>::kNegInfinity)
157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return strm << "-Infinity";
158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (w.Value() != w.Value())   // Fails for NaN
159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return strm << "BadNumber";
160f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else
161f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return strm << w.Value();
162f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
163f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
164f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
165f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline istream &operator>>(istream &strm, FloatWeightTpl<T> &w) {
166f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  string s;
167f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  strm >> s;
168f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (s == "Infinity") {
169f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    w = FloatWeightTpl<T>(FloatLimits<T>::kPosInfinity);
170f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else if (s == "-Infinity") {
171f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    w = FloatWeightTpl<T>(FloatLimits<T>::kNegInfinity);
172f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else {
173f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    char *p;
174f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    T f = strtod(s.c_str(), &p);
175f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (p < s.c_str() + s.size())
176f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      strm.clear(std::ios::badbit);
177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
178f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      w = FloatWeightTpl<T>(f);
179f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
180f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return strm;
181f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Tropical semiring: (min, +, inf, 0)
185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass TropicalWeightTpl : public FloatWeightTpl<T> {
187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using FloatWeightTpl<T>::Value;
189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef TropicalWeightTpl<T> ReverseWeight;
191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TropicalWeightTpl() : FloatWeightTpl<T>() {}
193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TropicalWeightTpl(T f) : FloatWeightTpl<T>(f) {}
195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TropicalWeightTpl(const TropicalWeightTpl<T> &w) : FloatWeightTpl<T>(w) {}
197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const TropicalWeightTpl<T> Zero() {
199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return TropicalWeightTpl<T>(FloatLimits<T>::kPosInfinity); }
200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const TropicalWeightTpl<T> One() {
202f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return TropicalWeightTpl<T>(0.0F); }
203f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
204f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const TropicalWeightTpl<T> NoWeight() {
205f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return TropicalWeightTpl<T>(FloatLimits<T>::kNumberBad); }
206f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
207f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const string &Type() {
208f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const string type = "tropical" +
209f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        FloatWeightTpl<T>::GetPrecisionString();
210f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return type;
211f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
212f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
213f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Member() const {
214f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // First part fails for IEEE NaN
215f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return Value() == Value() && Value() != FloatLimits<T>::kNegInfinity;
216f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
217f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
218f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TropicalWeightTpl<T> Quantize(float delta = kDelta) const {
219f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (Value() == FloatLimits<T>::kNegInfinity ||
220f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        Value() == FloatLimits<T>::kPosInfinity ||
221f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        Value() != Value())
222f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return *this;
223f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
224f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return TropicalWeightTpl<T>(floor(Value()/delta + 0.5F) * delta);
225f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
226f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
227f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TropicalWeightTpl<T> Reverse() const { return *this; }
228f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
229f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static uint64 Properties() {
230f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return kLeftSemiring | kRightSemiring | kCommutative |
231f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        kPath | kIdempotent;
232f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
233f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
234f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
235f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Single precision tropical weight
236f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef TropicalWeightTpl<float> TropicalWeight;
237f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
238f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
239f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline TropicalWeightTpl<T> Plus(const TropicalWeightTpl<T> &w1,
240f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                 const TropicalWeightTpl<T> &w2) {
241f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!w1.Member() || !w2.Member())
242f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return TropicalWeightTpl<T>::NoWeight();
243f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return w1.Value() < w2.Value() ? w1 : w2;
244f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
245f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
246f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline TropicalWeightTpl<float> Plus(const TropicalWeightTpl<float> &w1,
247f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                     const TropicalWeightTpl<float> &w2) {
248f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Plus<float>(w1, w2);
249f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
250f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
251f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline TropicalWeightTpl<double> Plus(const TropicalWeightTpl<double> &w1,
252f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                      const TropicalWeightTpl<double> &w2) {
253f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Plus<double>(w1, w2);
254f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
255f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
256f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
257f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline TropicalWeightTpl<T> Times(const TropicalWeightTpl<T> &w1,
258f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                  const TropicalWeightTpl<T> &w2) {
259f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!w1.Member() || !w2.Member())
260f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return TropicalWeightTpl<T>::NoWeight();
261f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T f1 = w1.Value(), f2 = w2.Value();
262f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (f1 == FloatLimits<T>::kPosInfinity)
263f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w1;
264f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (f2 == FloatLimits<T>::kPosInfinity)
265f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w2;
266f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else
267f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return TropicalWeightTpl<T>(f1 + f2);
268f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
269f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
270f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline TropicalWeightTpl<float> Times(const TropicalWeightTpl<float> &w1,
271f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                      const TropicalWeightTpl<float> &w2) {
272f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Times<float>(w1, w2);
273f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
274f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
275f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline TropicalWeightTpl<double> Times(const TropicalWeightTpl<double> &w1,
276f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                       const TropicalWeightTpl<double> &w2) {
277f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Times<double>(w1, w2);
278f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
279f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
280f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
281f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline TropicalWeightTpl<T> Divide(const TropicalWeightTpl<T> &w1,
282f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                   const TropicalWeightTpl<T> &w2,
283f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                   DivideType typ = DIVIDE_ANY) {
284f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!w1.Member() || !w2.Member())
285f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return TropicalWeightTpl<T>::NoWeight();
286f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T f1 = w1.Value(), f2 = w2.Value();
287f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (f2 == FloatLimits<T>::kPosInfinity)
288f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return FloatLimits<T>::kNumberBad;
289f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (f1 == FloatLimits<T>::kPosInfinity)
290f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return FloatLimits<T>::kPosInfinity;
291f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else
292f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return TropicalWeightTpl<T>(f1 - f2);
293f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
294f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
295f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline TropicalWeightTpl<float> Divide(const TropicalWeightTpl<float> &w1,
296f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                       const TropicalWeightTpl<float> &w2,
297f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                       DivideType typ = DIVIDE_ANY) {
298f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Divide<float>(w1, w2, typ);
299f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
300f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
301f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline TropicalWeightTpl<double> Divide(const TropicalWeightTpl<double> &w1,
302f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                        const TropicalWeightTpl<double> &w2,
303f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                        DivideType typ = DIVIDE_ANY) {
304f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Divide<double>(w1, w2, typ);
305f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
306f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
307f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
308f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Log semiring: (log(e^-x + e^y), +, inf, 0)
309f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
310f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass LogWeightTpl : public FloatWeightTpl<T> {
311f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
312f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using FloatWeightTpl<T>::Value;
313f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
314f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef LogWeightTpl ReverseWeight;
315f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
316f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  LogWeightTpl() : FloatWeightTpl<T>() {}
317f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
318f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  LogWeightTpl(T f) : FloatWeightTpl<T>(f) {}
319f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
320f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  LogWeightTpl(const LogWeightTpl<T> &w) : FloatWeightTpl<T>(w) {}
321f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
322f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const LogWeightTpl<T> Zero() {
323f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return LogWeightTpl<T>(FloatLimits<T>::kPosInfinity);
324f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
325f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
326f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const LogWeightTpl<T> One() {
327f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return LogWeightTpl<T>(0.0F);
328f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
329f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
330f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const LogWeightTpl<T> NoWeight() {
331f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return LogWeightTpl<T>(FloatLimits<T>::kNumberBad); }
332f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
333f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const string &Type() {
334f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const string type = "log" + FloatWeightTpl<T>::GetPrecisionString();
335f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return type;
336f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
337f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
338f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Member() const {
339f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // First part fails for IEEE NaN
340f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return Value() == Value() && Value() != FloatLimits<T>::kNegInfinity;
341f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
342f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
343f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  LogWeightTpl<T> Quantize(float delta = kDelta) const {
344f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (Value() == FloatLimits<T>::kNegInfinity ||
345f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        Value() == FloatLimits<T>::kPosInfinity ||
346f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        Value() != Value())
347f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return *this;
348f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
349f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return LogWeightTpl<T>(floor(Value()/delta + 0.5F) * delta);
350f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
351f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
352f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  LogWeightTpl<T> Reverse() const { return *this; }
353f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
354f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static uint64 Properties() {
355f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return kLeftSemiring | kRightSemiring | kCommutative;
356f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
357f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
358f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
359f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Single-precision log weight
360f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef LogWeightTpl<float> LogWeight;
361f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Double-precision log weight
362f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef LogWeightTpl<double> Log64Weight;
363f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
364f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
365f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline T LogExp(T x) { return log(1.0F + exp(-x)); }
366f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
367f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
368f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline LogWeightTpl<T> Plus(const LogWeightTpl<T> &w1,
369f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                            const LogWeightTpl<T> &w2) {
370f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T f1 = w1.Value(), f2 = w2.Value();
371f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (f1 == FloatLimits<T>::kPosInfinity)
372f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w2;
373f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (f2 == FloatLimits<T>::kPosInfinity)
374f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w1;
375f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (f1 > f2)
376f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return LogWeightTpl<T>(f2 - LogExp(f1 - f2));
377f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else
378f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return LogWeightTpl<T>(f1 - LogExp(f2 - f1));
379f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
380f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
381f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline LogWeightTpl<float> Plus(const LogWeightTpl<float> &w1,
382f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                const LogWeightTpl<float> &w2) {
383f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Plus<float>(w1, w2);
384f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
385f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
386f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline LogWeightTpl<double> Plus(const LogWeightTpl<double> &w1,
387f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                 const LogWeightTpl<double> &w2) {
388f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Plus<double>(w1, w2);
389f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
390f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
391f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
392f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline LogWeightTpl<T> Times(const LogWeightTpl<T> &w1,
393f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                             const LogWeightTpl<T> &w2) {
394f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!w1.Member() || !w2.Member())
395f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return LogWeightTpl<T>::NoWeight();
396f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T f1 = w1.Value(), f2 = w2.Value();
397f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (f1 == FloatLimits<T>::kPosInfinity)
398f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w1;
399f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (f2 == FloatLimits<T>::kPosInfinity)
400f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w2;
401f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else
402f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return LogWeightTpl<T>(f1 + f2);
403f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
404f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
405f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline LogWeightTpl<float> Times(const LogWeightTpl<float> &w1,
406f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                 const LogWeightTpl<float> &w2) {
407f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Times<float>(w1, w2);
408f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
409f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
410f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline LogWeightTpl<double> Times(const LogWeightTpl<double> &w1,
411f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                  const LogWeightTpl<double> &w2) {
412f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Times<double>(w1, w2);
413f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
414f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
415f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
416f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline LogWeightTpl<T> Divide(const LogWeightTpl<T> &w1,
417f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                              const LogWeightTpl<T> &w2,
418f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                              DivideType typ = DIVIDE_ANY) {
419f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!w1.Member() || !w2.Member())
420f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return LogWeightTpl<T>::NoWeight();
421f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T f1 = w1.Value(), f2 = w2.Value();
422f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (f2 == FloatLimits<T>::kPosInfinity)
423f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return FloatLimits<T>::kNumberBad;
424f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (f1 == FloatLimits<T>::kPosInfinity)
425f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return FloatLimits<T>::kPosInfinity;
426f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else
427f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return LogWeightTpl<T>(f1 - f2);
428f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
429f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
430f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline LogWeightTpl<float> Divide(const LogWeightTpl<float> &w1,
431f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                  const LogWeightTpl<float> &w2,
432f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                  DivideType typ = DIVIDE_ANY) {
433f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Divide<float>(w1, w2, typ);
434f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
435f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
436f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline LogWeightTpl<double> Divide(const LogWeightTpl<double> &w1,
437f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                   const LogWeightTpl<double> &w2,
438f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                   DivideType typ = DIVIDE_ANY) {
439f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Divide<double>(w1, w2, typ);
440f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
441f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
442f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// MinMax semiring: (min, max, inf, -inf)
443f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
444f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass MinMaxWeightTpl : public FloatWeightTpl<T> {
445f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
446f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using FloatWeightTpl<T>::Value;
447f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
448f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef MinMaxWeightTpl<T> ReverseWeight;
449f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
450f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MinMaxWeightTpl() : FloatWeightTpl<T>() {}
451f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
452f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MinMaxWeightTpl(T f) : FloatWeightTpl<T>(f) {}
453f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
454f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MinMaxWeightTpl(const MinMaxWeightTpl<T> &w) : FloatWeightTpl<T>(w) {}
455f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
456f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const MinMaxWeightTpl<T> Zero() {
457f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return MinMaxWeightTpl<T>(FloatLimits<T>::kPosInfinity);
458f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
459f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
460f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const MinMaxWeightTpl<T> One() {
461f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return MinMaxWeightTpl<T>(FloatLimits<T>::kNegInfinity);
462f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
463f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
464f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const MinMaxWeightTpl<T> NoWeight() {
465f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return MinMaxWeightTpl<T>(FloatLimits<T>::kNumberBad); }
466f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
467f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const string &Type() {
468f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const string type = "minmax" +
469f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        FloatWeightTpl<T>::GetPrecisionString();
470f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return type;
471f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
472f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
473f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Member() const {
474f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Fails for IEEE NaN
475f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return Value() == Value();
476f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
477f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
478f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MinMaxWeightTpl<T> Quantize(float delta = kDelta) const {
479f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // If one of infinities, or a NaN
480f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (Value() == FloatLimits<T>::kNegInfinity ||
481f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        Value() == FloatLimits<T>::kPosInfinity ||
482f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        Value() != Value())
483f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return *this;
484f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
485f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return MinMaxWeightTpl<T>(floor(Value()/delta + 0.5F) * delta);
486f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
487f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
488f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MinMaxWeightTpl<T> Reverse() const { return *this; }
489f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
490f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static uint64 Properties() {
491f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return kLeftSemiring | kRightSemiring | kCommutative | kIdempotent | kPath;
492f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
493f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
494f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
495f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Single-precision min-max weight
496f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef MinMaxWeightTpl<float> MinMaxWeight;
497f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
498f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Min
499f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
500f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline MinMaxWeightTpl<T> Plus(
501f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    const MinMaxWeightTpl<T> &w1, const MinMaxWeightTpl<T> &w2) {
502f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!w1.Member() || !w2.Member())
503f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return MinMaxWeightTpl<T>::NoWeight();
504f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return w1.Value() < w2.Value() ? w1 : w2;
505f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
506f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
507f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline MinMaxWeightTpl<float> Plus(
508f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    const MinMaxWeightTpl<float> &w1, const MinMaxWeightTpl<float> &w2) {
509f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Plus<float>(w1, w2);
510f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
511f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
512f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline MinMaxWeightTpl<double> Plus(
513f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    const MinMaxWeightTpl<double> &w1, const MinMaxWeightTpl<double> &w2) {
514f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Plus<double>(w1, w2);
515f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
516f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
517f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Max
518f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
519f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline MinMaxWeightTpl<T> Times(
520f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    const MinMaxWeightTpl<T> &w1, const MinMaxWeightTpl<T> &w2) {
521f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!w1.Member() || !w2.Member())
522f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return MinMaxWeightTpl<T>::NoWeight();
523f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return w1.Value() >= w2.Value() ? w1 : w2;
524f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
525f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
526f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline MinMaxWeightTpl<float> Times(
527f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    const MinMaxWeightTpl<float> &w1, const MinMaxWeightTpl<float> &w2) {
528f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Times<float>(w1, w2);
529f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
530f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
531f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline MinMaxWeightTpl<double> Times(
532f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    const MinMaxWeightTpl<double> &w1, const MinMaxWeightTpl<double> &w2) {
533f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Times<double>(w1, w2);
534f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
535f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
536f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Defined only for special cases
537f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
538f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline MinMaxWeightTpl<T> Divide(const MinMaxWeightTpl<T> &w1,
539f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                 const MinMaxWeightTpl<T> &w2,
540f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                 DivideType typ = DIVIDE_ANY) {
541f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!w1.Member() || !w2.Member())
542f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return MinMaxWeightTpl<T>::NoWeight();
543f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // min(w1, x) = w2, w1 >= w2 => min(w1, x) = w2, x = w2
544f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return w1.Value() >= w2.Value() ? w1 : FloatLimits<T>::kNumberBad;
545f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
546f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
547f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline MinMaxWeightTpl<float> Divide(const MinMaxWeightTpl<float> &w1,
548f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                     const MinMaxWeightTpl<float> &w2,
549f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                     DivideType typ = DIVIDE_ANY) {
550f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Divide<float>(w1, w2, typ);
551f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
552f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
553f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline MinMaxWeightTpl<double> Divide(const MinMaxWeightTpl<double> &w1,
554f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                      const MinMaxWeightTpl<double> &w2,
555f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                      DivideType typ = DIVIDE_ANY) {
556f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Divide<double>(w1, w2, typ);
557f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
558f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
559f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
560f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WEIGHT CONVERTER SPECIALIZATIONS.
561f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
562f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
563f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Convert to tropical
564f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
565f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<LogWeight, TropicalWeight> {
566f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TropicalWeight operator()(LogWeight w) const { return w.Value(); }
567f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
568f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
569f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
570f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<Log64Weight, TropicalWeight> {
571f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TropicalWeight operator()(Log64Weight w) const { return w.Value(); }
572f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
573f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
574f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Convert to log
575f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
576f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<TropicalWeight, LogWeight> {
577f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  LogWeight operator()(TropicalWeight w) const { return w.Value(); }
578f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
579f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
580f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
581f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<Log64Weight, LogWeight> {
582f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  LogWeight operator()(Log64Weight w) const { return w.Value(); }
583f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
584f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
585f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Convert to log64
586f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
587f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<TropicalWeight, Log64Weight> {
588f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Log64Weight operator()(TropicalWeight w) const { return w.Value(); }
589f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
590f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
591f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
592f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<LogWeight, Log64Weight> {
593f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Log64Weight operator()(LogWeight w) const { return w.Value(); }
594f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
595f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
596f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}  // namespace fst
597f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
598f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif  // FST_LIB_FLOAT_WEIGHT_H__
599