signed-log-weight.h revision f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Licensed under the Apache License, Version 2.0 (the "License");
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// you may not use this file except in compliance with the License.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// You may obtain a copy of the License at
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     http://www.apache.org/licenses/LICENSE-2.0
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Unless required by applicable law or agreed to in writing, software
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distributed under the License is distributed on an "AS IS" BASIS,
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See the License for the specific language governing permissions and
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// limitations under the License.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2005-2010 Google, Inc.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: krr@google.com (Kasturi Rangan Raghavan)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// \file
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LogWeight along with sign information that represents the value X in the
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// linear domain as <sign(X), -ln(|X|)>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The sign is a TropicalWeight:
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  positive, TropicalWeight.Value() > 0.0, recommended value 1.0
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  negative, TropicalWeight.Value() <= 0.0, recommended value -1.0
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef FST_LIB_SIGNED_LOG_WEIGHT_H_
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FST_LIB_SIGNED_LOG_WEIGHT_H_
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fst/float-weight.h>
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fst/pair-weight.h>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace fst {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <class T>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SignedLogWeightTpl
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public PairWeight<TropicalWeight, LogWeightTpl<T> > {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef TropicalWeight X1;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef LogWeightTpl<T> X2;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using PairWeight<X1, X2>::Value1;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  using PairWeight<X1, X2>::Value2;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using PairWeight<X1, X2>::Reverse;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using PairWeight<X1, X2>::Quantize;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using PairWeight<X1, X2>::Member;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef SignedLogWeightTpl<T> ReverseWeight;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLogWeightTpl() : PairWeight<X1, X2>() {}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLogWeightTpl(const SignedLogWeightTpl<T>& w)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : PairWeight<X1, X2> (w) { }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLogWeightTpl(const PairWeight<X1, X2>& w)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : PairWeight<X1, X2> (w) { }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SignedLogWeightTpl(const X1& x1, const X2& x2)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : PairWeight<X1, X2>(x1, x2) { }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const SignedLogWeightTpl<T> &Zero() {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const SignedLogWeightTpl<T> zero(X1(1.0), X2::Zero());
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return zero;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const SignedLogWeightTpl<T> &One() {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static const SignedLogWeightTpl<T> one(X1(1.0), X2::One());
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return one;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const SignedLogWeightTpl<T> &NoWeight() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const SignedLogWeightTpl<T> no_weight(X1(1.0), X2::NoWeight());
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return no_weight;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const string &Type() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const string type = "signed_log_" + X1::Type() + "_" + X2::Type();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return type;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProductWeight<X1, X2> Quantize(float delta = kDelta) const {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return PairWeight<X1, X2>::Quantize();
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReverseWeight Reverse() const {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return PairWeight<X1, X2>::Reverse();
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool Member() const {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return PairWeight<X1, X2>::Member();
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static uint64 Properties() {
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // not idempotent nor path
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return kLeftSemiring | kRightSemiring | kCommutative;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t Hash() const {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t h1;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (Value2() == X2::Zero() || Value1().Value() > 0.0)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      h1 = TropicalWeight(1.0).Hash();
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      h1 = TropicalWeight(-1.0).Hash();
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t h2 = Value2().Hash();
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int lshift = 5;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int rshift = CHAR_BIT * sizeof(size_t) - 5;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return h1 << lshift ^ h1 >> rshift ^ h2;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <class T>
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)inline SignedLogWeightTpl<T> Plus(const SignedLogWeightTpl<T> &w1,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const SignedLogWeightTpl<T> &w2) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!w1.Member() || !w2.Member())
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return SignedLogWeightTpl<T>::NoWeight();
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool s1 = w1.Value1().Value() > 0.0;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool s2 = w2.Value1().Value() > 0.0;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  T f1 = w1.Value2().Value();
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  T f2 = w2.Value2().Value();
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (f1 == FloatLimits<T>::kPosInfinity)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return w2;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (f2 == FloatLimits<T>::kPosInfinity)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return w1;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (f1 == f2) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (s1 == s2)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return SignedLogWeightTpl<T>(w1.Value1(), (f2 - log(2.0F)));
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return SignedLogWeightTpl<T>::Zero();
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (f1 > f2) {
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (s1 == s2) {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return SignedLogWeightTpl<T>(
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        w1.Value1(), (f2 - log(1.0F + exp(f2 - f1))));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SignedLogWeightTpl<T>(
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        w2.Value1(), (f2 - log(1.0F - exp(f2 - f1))));
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (s2 == s1) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SignedLogWeightTpl<T>(
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        w2.Value1(), (f1 - log(1.0F + exp(f1 - f2))));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SignedLogWeightTpl<T>(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        w1.Value1(), (f1 - log(1.0F - exp(f1 - f2))));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T>
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline SignedLogWeightTpl<T> Minus(const SignedLogWeightTpl<T> &w1,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const SignedLogWeightTpl<T> &w2) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLogWeightTpl<T> minus_w2(-w2.Value1().Value(), w2.Value2());
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Plus(w1, minus_w2);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T>
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline SignedLogWeightTpl<T> Times(const SignedLogWeightTpl<T> &w1,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const SignedLogWeightTpl<T> &w2) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!w1.Member() || !w2.Member())
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeightTpl<T>::NoWeight();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool s1 = w1.Value1().Value() > 0.0;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool s2 = w2.Value1().Value() > 0.0;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T f1 = w1.Value2().Value();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T f2 = w2.Value2().Value();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (s1 == s2)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeightTpl<T>(TropicalWeight(1.0), (f1 + f2));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeightTpl<T>(TropicalWeight(-1.0), (f1 + f2));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T>
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline SignedLogWeightTpl<T> Divide(const SignedLogWeightTpl<T> &w1,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const SignedLogWeightTpl<T> &w2,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    DivideType typ = DIVIDE_ANY) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!w1.Member() || !w2.Member())
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeightTpl<T>::NoWeight();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool s1 = w1.Value1().Value() > 0.0;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool s2 = w2.Value1().Value() > 0.0;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T f1 = w1.Value2().Value();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T f2 = w2.Value2().Value();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (f2 == FloatLimits<T>::kPosInfinity)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeightTpl<T>(TropicalWeight(1.0),
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FloatLimits<T>::kNumberBad);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (f1 == FloatLimits<T>::kPosInfinity)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeightTpl<T>(TropicalWeight(1.0),
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FloatLimits<T>::kPosInfinity);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (s1 == s2)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeightTpl<T>(TropicalWeight(1.0), (f1 - f2));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeightTpl<T>(TropicalWeight(-1.0), (f1 - f2));
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T>
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool ApproxEqual(const SignedLogWeightTpl<T> &w1,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const SignedLogWeightTpl<T> &w2,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        float delta = kDelta) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool s1 = w1.Value1().Value() > 0.0;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool s2 = w2.Value1().Value() > 0.0;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (s1 == s2) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ApproxEqual(w1.Value2(), w2.Value2(), delta);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return w1.Value2() == LogWeightTpl<T>::Zero()
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && w2.Value2() == LogWeightTpl<T>::Zero();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T>
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool operator==(const SignedLogWeightTpl<T> &w1,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const SignedLogWeightTpl<T> &w2) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool s1 = w1.Value1().Value() > 0.0;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool s2 = w2.Value1().Value() > 0.0;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (s1 == s2)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return w1.Value2() == w2.Value2();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (w1.Value2() == LogWeightTpl<T>::Zero()) &&
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (w2.Value2() == LogWeightTpl<T>::Zero());
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Single-precision signed-log weight
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SignedLogWeightTpl<float> SignedLogWeight;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Double-precision signed-log weight
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SignedLogWeightTpl<double> SignedLog64Weight;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WEIGHT CONVERTER SPECIALIZATIONS.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class W1, class W2>
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SignedLogConvertCheck(W1 w) {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (w.Value1().Value() < 0.0) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FSTERROR() << "WeightConvert: can't convert weight from \""
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << W1::Type() << "\" to \"" << W2::Type();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert to tropical
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<SignedLogWeight, TropicalWeight> {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TropicalWeight operator()(SignedLogWeight w) const {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SignedLogConvertCheck<SignedLogWeight, TropicalWeight>(w))
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TropicalWeight::NoWeight();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return w.Value2().Value();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<SignedLog64Weight, TropicalWeight> {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TropicalWeight operator()(SignedLog64Weight w) const {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SignedLogConvertCheck<SignedLog64Weight, TropicalWeight>(w))
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TropicalWeight::NoWeight();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return w.Value2().Value();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert to log
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<SignedLogWeight, LogWeight> {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogWeight operator()(SignedLogWeight w) const {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SignedLogConvertCheck<SignedLogWeight, LogWeight>(w))
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return LogWeight::NoWeight();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return w.Value2().Value();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<SignedLog64Weight, LogWeight> {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogWeight operator()(SignedLog64Weight w) const {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SignedLogConvertCheck<SignedLog64Weight, LogWeight>(w))
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return LogWeight::NoWeight();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return w.Value2().Value();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert to log64
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<SignedLogWeight, Log64Weight> {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Log64Weight operator()(SignedLogWeight w) const {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SignedLogConvertCheck<SignedLogWeight, Log64Weight>(w))
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Log64Weight::NoWeight();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return w.Value2().Value();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<SignedLog64Weight, Log64Weight> {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Log64Weight operator()(SignedLog64Weight w) const {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SignedLogConvertCheck<SignedLog64Weight, Log64Weight>(w))
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Log64Weight::NoWeight();
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return w.Value2().Value();
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert to signed log
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<TropicalWeight, SignedLogWeight> {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLogWeight operator()(TropicalWeight w) const {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TropicalWeight x1 = 1.0;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogWeight x2 = w.Value();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeight(x1, x2);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<LogWeight, SignedLogWeight> {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLogWeight operator()(LogWeight w) const {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TropicalWeight x1 = 1.0;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogWeight x2 = w.Value();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeight(x1, x2);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<Log64Weight, SignedLogWeight> {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLogWeight operator()(Log64Weight w) const {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TropicalWeight x1 = 1.0;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogWeight x2 = w.Value();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeight(x1, x2);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<SignedLog64Weight, SignedLogWeight> {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLogWeight operator()(SignedLog64Weight w) const {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TropicalWeight x1 = w.Value1();
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogWeight x2 = w.Value2().Value();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLogWeight(x1, x2);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert to signed log64
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<TropicalWeight, SignedLog64Weight> {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLog64Weight operator()(TropicalWeight w) const {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TropicalWeight x1 = 1.0;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Log64Weight x2 = w.Value();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLog64Weight(x1, x2);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<LogWeight, SignedLog64Weight> {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLog64Weight operator()(LogWeight w) const {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TropicalWeight x1 = 1.0;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Log64Weight x2 = w.Value();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLog64Weight(x1, x2);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<Log64Weight, SignedLog64Weight> {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLog64Weight operator()(Log64Weight w) const {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TropicalWeight x1 = 1.0;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Log64Weight x2 = w.Value();
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLog64Weight(x1, x2);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WeightConvert<SignedLogWeight, SignedLog64Weight> {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignedLog64Weight operator()(SignedLogWeight w) const {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TropicalWeight x1 = w.Value1();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Log64Weight x2 = w.Value2().Value();
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SignedLog64Weight(x1, x2);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace fst
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // FST_LIB_SIGNED_LOG_WEIGHT_H_
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)