// lat/arctic-weight.h // Copyright 2012 Johns Hopkins University (Author: Guoguo Chen) // See ../../COPYING for clarification regarding multiple authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, // MERCHANTABLITY OR NON-INFRINGEMENT. // See the Apache 2 License for the specific language governing permissions and // limitations under the License. #ifndef KALDI_LAT_ARCTIC_WEIGHT_H_ #define KALDI_LAT_ARCTIC_WEIGHT_H_ #include "fst/float-weight.h" namespace fst { // Arctic semiring: (max, +, inf, 0) // We define the Arctic semiring T' = (R \cup {-inf, +inf}, max, +, -inf, 0). // The term "Arctic" came from Keith Kintzley (kintzley@jhu.edu), as opposite // to the Tropical semiring. template class ArcticWeightTpl : public FloatWeightTpl { public: using FloatWeightTpl::Value; typedef ArcticWeightTpl ReverseWeight; ArcticWeightTpl() : FloatWeightTpl() {} ArcticWeightTpl(T f) : FloatWeightTpl(f) {} ArcticWeightTpl(const ArcticWeightTpl &w) : FloatWeightTpl(w) {} static const ArcticWeightTpl Zero() { return ArcticWeightTpl(-std::numeric_limits::infinity()); } static const ArcticWeightTpl One() { return ArcticWeightTpl(0.0F); } static const std::string &Type() { static const std::string type = std::string("arctic") + FloatWeightTpl::GetPrecisionString(); return type; } static ArcticWeightTpl NoWeight() { return ArcticWeightTpl(std::numeric_limits::infinity()); } bool Member() const { // First part fails for IEEE NaN return Value() == Value() && Value() != std::numeric_limits::infinity(); } ArcticWeightTpl Quantize(float delta = kDelta) const { if (Value() == -std::numeric_limits::infinity() || Value() == std::numeric_limits::infinity() || Value() != Value()) return *this; else return ArcticWeightTpl(floor(Value()/delta + 0.5F) * delta); } ArcticWeightTpl Reverse() const { return *this; } static uint64 Properties() { return kLeftSemiring | kRightSemiring | kCommutative | kPath | kIdempotent; } }; // Single precision arctic weight typedef ArcticWeightTpl ArcticWeight; template inline ArcticWeightTpl Plus(const ArcticWeightTpl &w1, const ArcticWeightTpl &w2) { return w1.Value() > w2.Value() ? w1 : w2; } inline ArcticWeightTpl Plus(const ArcticWeightTpl &w1, const ArcticWeightTpl &w2) { return Plus(w1, w2); } inline ArcticWeightTpl Plus(const ArcticWeightTpl &w1, const ArcticWeightTpl &w2) { return Plus(w1, w2); } template inline ArcticWeightTpl Times(const ArcticWeightTpl &w1, const ArcticWeightTpl &w2) { T f1 = w1.Value(), f2 = w2.Value(); if (f1 == -std::numeric_limits::infinity()) return w1; else if (f2 == -std::numeric_limits::infinity()) return w2; else return ArcticWeightTpl(f1 + f2); } inline ArcticWeightTpl Times(const ArcticWeightTpl &w1, const ArcticWeightTpl &w2) { return Times(w1, w2); } inline ArcticWeightTpl Times(const ArcticWeightTpl &w1, const ArcticWeightTpl &w2) { return Times(w1, w2); } template inline ArcticWeightTpl Divide(const ArcticWeightTpl &w1, const ArcticWeightTpl &w2, DivideType typ = DIVIDE_ANY) { T f1 = w1.Value(), f2 = w2.Value(); if (f2 == -std::numeric_limits::infinity()) return std::numeric_limits::quiet_NaN(); else if (f1 == -std::numeric_limits::infinity()) return -std::numeric_limits::infinity(); else return ArcticWeightTpl(f1 - f2); } inline ArcticWeightTpl Divide(const ArcticWeightTpl &w1, const ArcticWeightTpl &w2, DivideType typ = DIVIDE_ANY) { return Divide(w1, w2, typ); } inline ArcticWeightTpl Divide(const ArcticWeightTpl &w1, const ArcticWeightTpl &w2, DivideType typ = DIVIDE_ANY) { return Divide(w1, w2, typ); } } // namespace fst #endif // KALDI_LAT_ARCTIC_WEIGHT_H_