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