1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License");
3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License.
4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at
5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     http://www.apache.org/licenses/LICENSE-2.0
7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software
9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS,
10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and
12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License.
13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc.
15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: krr@google.com (Kasturi Rangan Raghavan)
16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// \file
17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// LogWeight along with sign information that represents the value X in the
18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// linear domain as <sign(X), -ln(|X|)>
19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// The sign is a TropicalWeight:
20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  positive, TropicalWeight.Value() > 0.0, recommended value 1.0
21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  negative, TropicalWeight.Value() <= 0.0, recommended value -1.0
22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_LIB_SIGNED_LOG_WEIGHT_H_
24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_LIB_SIGNED_LOG_WEIGHT_H_
25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
26f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/float-weight.h>
27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/pair-weight.h>
28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst {
31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass SignedLogWeightTpl
33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    : public PairWeight<TropicalWeight, LogWeightTpl<T> > {
34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef TropicalWeight X1;
36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef LogWeightTpl<T> X2;
37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using PairWeight<X1, X2>::Value1;
38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using PairWeight<X1, X2>::Value2;
39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using PairWeight<X1, X2>::Reverse;
41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using PairWeight<X1, X2>::Quantize;
42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  using PairWeight<X1, X2>::Member;
43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef SignedLogWeightTpl<T> ReverseWeight;
45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLogWeightTpl() : PairWeight<X1, X2>() {}
47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLogWeightTpl(const SignedLogWeightTpl<T>& w)
49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : PairWeight<X1, X2> (w) { }
50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLogWeightTpl(const PairWeight<X1, X2>& w)
52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : PairWeight<X1, X2> (w) { }
53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLogWeightTpl(const X1& x1, const X2& x2)
55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : PairWeight<X1, X2>(x1, x2) { }
56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const SignedLogWeightTpl<T> &Zero() {
58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const SignedLogWeightTpl<T> zero(X1(1.0), X2::Zero());
59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return zero;
60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const SignedLogWeightTpl<T> &One() {
63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const SignedLogWeightTpl<T> one(X1(1.0), X2::One());
64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return one;
65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const SignedLogWeightTpl<T> &NoWeight() {
68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const SignedLogWeightTpl<T> no_weight(X1(1.0), X2::NoWeight());
69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return no_weight;
70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const string &Type() {
73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    static const string type = "signed_log_" + X1::Type() + "_" + X2::Type();
74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return type;
75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ProductWeight<X1, X2> Quantize(float delta = kDelta) const {
78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return PairWeight<X1, X2>::Quantize();
79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ReverseWeight Reverse() const {
82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return PairWeight<X1, X2>::Reverse();
83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Member() const {
86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return PairWeight<X1, X2>::Member();
87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static uint64 Properties() {
90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // not idempotent nor path
91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return kLeftSemiring | kRightSemiring | kCommutative;
92f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
93f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
94f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  size_t Hash() const {
95f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    size_t h1;
96f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (Value2() == X2::Zero() || Value1().Value() > 0.0)
97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      h1 = TropicalWeight(1.0).Hash();
98f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      h1 = TropicalWeight(-1.0).Hash();
100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    size_t h2 = Value2().Hash();
101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    const int lshift = 5;
102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    const int rshift = CHAR_BIT * sizeof(size_t) - 5;
103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return h1 << lshift ^ h1 >> rshift ^ h2;
104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline SignedLogWeightTpl<T> Plus(const SignedLogWeightTpl<T> &w1,
109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                  const SignedLogWeightTpl<T> &w2) {
110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!w1.Member() || !w2.Member())
111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeightTpl<T>::NoWeight();
112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool s1 = w1.Value1().Value() > 0.0;
113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool s2 = w2.Value1().Value() > 0.0;
114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T f1 = w1.Value2().Value();
115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T f2 = w2.Value2().Value();
116dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  if (f1 == FloatLimits<T>::PosInfinity())
117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w2;
118dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  else if (f2 == FloatLimits<T>::PosInfinity())
119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w1;
120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (f1 == f2) {
121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (s1 == s2)
122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return SignedLogWeightTpl<T>(w1.Value1(), (f2 - log(2.0F)));
123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return SignedLogWeightTpl<T>::Zero();
125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else if (f1 > f2) {
126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (s1 == s2) {
127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return SignedLogWeightTpl<T>(
128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        w1.Value1(), (f2 - log(1.0F + exp(f2 - f1))));
129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return SignedLogWeightTpl<T>(
131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        w2.Value1(), (f2 - log(1.0F - exp(f2 - f1))));
132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else {
134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (s2 == s1) {
135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return SignedLogWeightTpl<T>(
136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        w2.Value1(), (f1 - log(1.0F + exp(f1 - f2))));
137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return SignedLogWeightTpl<T>(
139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        w1.Value1(), (f1 - log(1.0F - exp(f1 - f2))));
140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline SignedLogWeightTpl<T> Minus(const SignedLogWeightTpl<T> &w1,
146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                   const SignedLogWeightTpl<T> &w2) {
147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLogWeightTpl<T> minus_w2(-w2.Value1().Value(), w2.Value2());
148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return Plus(w1, minus_w2);
149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline SignedLogWeightTpl<T> Times(const SignedLogWeightTpl<T> &w1,
153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                   const SignedLogWeightTpl<T> &w2) {
154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!w1.Member() || !w2.Member())
155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeightTpl<T>::NoWeight();
156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool s1 = w1.Value1().Value() > 0.0;
157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool s2 = w2.Value1().Value() > 0.0;
158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T f1 = w1.Value2().Value();
159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T f2 = w2.Value2().Value();
160f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (s1 == s2)
161f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeightTpl<T>(TropicalWeight(1.0), (f1 + f2));
162f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else
163f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeightTpl<T>(TropicalWeight(-1.0), (f1 + f2));
164f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
165f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
166f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
167f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline SignedLogWeightTpl<T> Divide(const SignedLogWeightTpl<T> &w1,
168f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                    const SignedLogWeightTpl<T> &w2,
169f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                                    DivideType typ = DIVIDE_ANY) {
170f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!w1.Member() || !w2.Member())
171f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeightTpl<T>::NoWeight();
172f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool s1 = w1.Value1().Value() > 0.0;
173f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool s2 = w2.Value1().Value() > 0.0;
174f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T f1 = w1.Value2().Value();
175f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  T f2 = w2.Value2().Value();
176dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  if (f2 == FloatLimits<T>::PosInfinity())
177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeightTpl<T>(TropicalWeight(1.0),
178dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      FloatLimits<T>::NumberBad());
179dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  else if (f1 == FloatLimits<T>::PosInfinity())
180f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeightTpl<T>(TropicalWeight(1.0),
181dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      FloatLimits<T>::PosInfinity());
182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else if (s1 == s2)
183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeightTpl<T>(TropicalWeight(1.0), (f1 - f2));
184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else
185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeightTpl<T>(TropicalWeight(-1.0), (f1 - f2));
186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool ApproxEqual(const SignedLogWeightTpl<T> &w1,
190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                        const SignedLogWeightTpl<T> &w2,
191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                        float delta = kDelta) {
192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool s1 = w1.Value1().Value() > 0.0;
193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool s2 = w2.Value1().Value() > 0.0;
194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (s1 == s2) {
195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return ApproxEqual(w1.Value2(), w2.Value2(), delta);
196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else {
197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w1.Value2() == LogWeightTpl<T>::Zero()
198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        && w2.Value2() == LogWeightTpl<T>::Zero();
199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
202f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T>
203f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsoninline bool operator==(const SignedLogWeightTpl<T> &w1,
204f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       const SignedLogWeightTpl<T> &w2) {
205f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool s1 = w1.Value1().Value() > 0.0;
206f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool s2 = w2.Value1().Value() > 0.0;
207f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (s1 == s2)
208f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w1.Value2() == w2.Value2();
209f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  else
210f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return (w1.Value2() == LogWeightTpl<T>::Zero()) &&
211f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson           (w2.Value2() == LogWeightTpl<T>::Zero());
212f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
213f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
214f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
215f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Single-precision signed-log weight
216f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef SignedLogWeightTpl<float> SignedLogWeight;
217f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Double-precision signed-log weight
218f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontypedef SignedLogWeightTpl<double> SignedLog64Weight;
219f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
220f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
221f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WEIGHT CONVERTER SPECIALIZATIONS.
222f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
223f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
224f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class W1, class W2>
225f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonbool SignedLogConvertCheck(W1 w) {
226f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (w.Value1().Value() < 0.0) {
227f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    FSTERROR() << "WeightConvert: can't convert weight from \""
228f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson               << W1::Type() << "\" to \"" << W2::Type();
229f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return false;
230f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
231f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return true;
232f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
233f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
234f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Convert to tropical
235f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
236f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<SignedLogWeight, TropicalWeight> {
237f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TropicalWeight operator()(SignedLogWeight w) const {
238f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!SignedLogConvertCheck<SignedLogWeight, TropicalWeight>(w))
239f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return TropicalWeight::NoWeight();
240f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w.Value2().Value();
241f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
242f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
243f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
244f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
245f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<SignedLog64Weight, TropicalWeight> {
246f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  TropicalWeight operator()(SignedLog64Weight w) const {
247f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!SignedLogConvertCheck<SignedLog64Weight, TropicalWeight>(w))
248f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return TropicalWeight::NoWeight();
249f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w.Value2().Value();
250f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
251f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
252f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
253f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Convert to log
254f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
255f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<SignedLogWeight, LogWeight> {
256f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  LogWeight operator()(SignedLogWeight w) const {
257f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!SignedLogConvertCheck<SignedLogWeight, LogWeight>(w))
258f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return LogWeight::NoWeight();
259f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w.Value2().Value();
260f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
261f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
262f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
263f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
264f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<SignedLog64Weight, LogWeight> {
265f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  LogWeight operator()(SignedLog64Weight w) const {
266f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!SignedLogConvertCheck<SignedLog64Weight, LogWeight>(w))
267f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return LogWeight::NoWeight();
268f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w.Value2().Value();
269f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
270f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
271f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
272f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Convert to log64
273f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
274f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<SignedLogWeight, Log64Weight> {
275f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Log64Weight operator()(SignedLogWeight w) const {
276f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!SignedLogConvertCheck<SignedLogWeight, Log64Weight>(w))
277f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return Log64Weight::NoWeight();
278f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w.Value2().Value();
279f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
280f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
281f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
282f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
283f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<SignedLog64Weight, Log64Weight> {
284f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Log64Weight operator()(SignedLog64Weight w) const {
285f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!SignedLogConvertCheck<SignedLog64Weight, Log64Weight>(w))
286f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return Log64Weight::NoWeight();
287f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return w.Value2().Value();
288f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
289f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
290f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
291f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Convert to signed log
292f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
293f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<TropicalWeight, SignedLogWeight> {
294f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLogWeight operator()(TropicalWeight w) const {
295f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    TropicalWeight x1 = 1.0;
296f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    LogWeight x2 = w.Value();
297f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeight(x1, x2);
298f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
299f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
300f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
301f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
302f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<LogWeight, SignedLogWeight> {
303f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLogWeight operator()(LogWeight w) const {
304f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    TropicalWeight x1 = 1.0;
305f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    LogWeight x2 = w.Value();
306f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeight(x1, x2);
307f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
308f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
309f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
310f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
311f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<Log64Weight, SignedLogWeight> {
312f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLogWeight operator()(Log64Weight w) const {
313f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    TropicalWeight x1 = 1.0;
314f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    LogWeight x2 = w.Value();
315f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeight(x1, x2);
316f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
317f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
318f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
319f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
320f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<SignedLog64Weight, SignedLogWeight> {
321f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLogWeight operator()(SignedLog64Weight w) const {
322f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    TropicalWeight x1 = w.Value1();
323f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    LogWeight x2 = w.Value2().Value();
324f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLogWeight(x1, x2);
325f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
326f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
327f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
328f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Convert to signed log64
329f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
330f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<TropicalWeight, SignedLog64Weight> {
331f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLog64Weight operator()(TropicalWeight w) const {
332f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    TropicalWeight x1 = 1.0;
333f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Log64Weight x2 = w.Value();
334f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLog64Weight(x1, x2);
335f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
336f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
337f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
338f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
339f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<LogWeight, SignedLog64Weight> {
340f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLog64Weight operator()(LogWeight w) const {
341f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    TropicalWeight x1 = 1.0;
342f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Log64Weight x2 = w.Value();
343f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLog64Weight(x1, x2);
344f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
345f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
346f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
347f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
348f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<Log64Weight, SignedLog64Weight> {
349f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLog64Weight operator()(Log64Weight w) const {
350f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    TropicalWeight x1 = 1.0;
351f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Log64Weight x2 = w.Value();
352f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLog64Weight(x1, x2);
353f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
354f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
355f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
356f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <>
357f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct WeightConvert<SignedLogWeight, SignedLog64Weight> {
358f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SignedLog64Weight operator()(SignedLogWeight w) const {
359f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    TropicalWeight x1 = w.Value1();
360f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Log64Weight x2 = w.Value2().Value();
361f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return SignedLog64Weight(x1, x2);
362f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
363f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
364f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
365f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}  // namespace fst
366f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
367f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif  // FST_LIB_SIGNED_LOG_WEIGHT_H_
368