00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef FST_LIB_FLOAT_WEIGHT_H__
00023 #define FST_LIB_FLOAT_WEIGHT_H__
00024
00025 #include <limits>
00026 #include <climits>
00027 #include <sstream>
00028 #include <string>
00029 #include <fst/util.h>
00030 #include <fst/weight.h>
00031
00032 namespace fst {
00033
00034
00035 template <class T>
00036 class FloatLimits {
00037 public:
00038 static const T kPosInfinity;
00039 static const T kNegInfinity;
00040 static const T kNumberBad;
00041 };
00042
00043 template <class T>
00044 const T FloatLimits<T>::kPosInfinity = numeric_limits<T>::infinity();
00045
00046 template <class T>
00047 const T FloatLimits<T>::kNegInfinity = -FloatLimits<T>::kPosInfinity;
00048
00049 template <class T>
00050 const T FloatLimits<T>::kNumberBad = numeric_limits<T>::quiet_NaN();
00051
00052
00053 template <class T = float>
00054 class FloatWeightTpl {
00055 public:
00056 FloatWeightTpl() {}
00057
00058 FloatWeightTpl(T f) : value_(f) {}
00059
00060 FloatWeightTpl(const FloatWeightTpl<T> &w) : value_(w.value_) {}
00061
00062 FloatWeightTpl<T> &operator=(const FloatWeightTpl<T> &w) {
00063 value_ = w.value_;
00064 return *this;
00065 }
00066
00067 istream &Read(istream &strm) {
00068 return ReadType(strm, &value_);
00069 }
00070
00071 ostream &Write(ostream &strm) const {
00072 return WriteType(strm, value_);
00073 }
00074
00075 size_t Hash() const {
00076 union {
00077 T f;
00078 size_t s;
00079 } u;
00080 u.s = 0;
00081 u.f = value_;
00082 return u.s;
00083 }
00084
00085 const T &Value() const { return value_; }
00086
00087 protected:
00088 inline static string GetPrecisionString() {
00089 int64 size = sizeof(T);
00090 if (size == sizeof(float)) return "";
00091 size *= CHAR_BIT;
00092
00093 string result;
00094 Int64ToStr(size, &result);
00095 return result;
00096 }
00097
00098 T value_;
00099 };
00100
00101
00102 typedef FloatWeightTpl<float> FloatWeight;
00103
00104 template <class T>
00105 inline bool operator==(const FloatWeightTpl<T> &w1,
00106 const FloatWeightTpl<T> &w2) {
00107
00108
00109 volatile T v1 = w1.Value();
00110 volatile T v2 = w2.Value();
00111 return v1 == v2;
00112 }
00113
00114 inline bool operator==(const FloatWeightTpl<double> &w1,
00115 const FloatWeightTpl<double> &w2) {
00116 return operator==<double>(w1, w2);
00117 }
00118
00119 inline bool operator==(const FloatWeightTpl<float> &w1,
00120 const FloatWeightTpl<float> &w2) {
00121 return operator==<float>(w1, w2);
00122 }
00123
00124 template <class T>
00125 inline bool operator!=(const FloatWeightTpl<T> &w1,
00126 const FloatWeightTpl<T> &w2) {
00127 return !(w1 == w2);
00128 }
00129
00130 inline bool operator!=(const FloatWeightTpl<double> &w1,
00131 const FloatWeightTpl<double> &w2) {
00132 return operator!=<double>(w1, w2);
00133 }
00134
00135 inline bool operator!=(const FloatWeightTpl<float> &w1,
00136 const FloatWeightTpl<float> &w2) {
00137 return operator!=<float>(w1, w2);
00138 }
00139
00140 template <class T>
00141 inline bool ApproxEqual(const FloatWeightTpl<T> &w1,
00142 const FloatWeightTpl<T> &w2,
00143 float delta = kDelta) {
00144 return w1.Value() <= w2.Value() + delta && w2.Value() <= w1.Value() + delta;
00145 }
00146
00147 template <class T>
00148 inline ostream &operator<<(ostream &strm, const FloatWeightTpl<T> &w) {
00149 if (w.Value() == FloatLimits<T>::kPosInfinity)
00150 return strm << "Infinity";
00151 else if (w.Value() == FloatLimits<T>::kNegInfinity)
00152 return strm << "-Infinity";
00153 else if (w.Value() != w.Value())
00154 return strm << "BadNumber";
00155 else
00156 return strm << w.Value();
00157 }
00158
00159 template <class T>
00160 inline istream &operator>>(istream &strm, FloatWeightTpl<T> &w) {
00161 string s;
00162 strm >> s;
00163 if (s == "Infinity") {
00164 w = FloatWeightTpl<T>(FloatLimits<T>::kPosInfinity);
00165 } else if (s == "-Infinity") {
00166 w = FloatWeightTpl<T>(FloatLimits<T>::kNegInfinity);
00167 } else {
00168 char *p;
00169 T f = strtod(s.c_str(), &p);
00170 if (p < s.c_str() + s.size())
00171 strm.clear(std::ios::badbit);
00172 else
00173 w = FloatWeightTpl<T>(f);
00174 }
00175 return strm;
00176 }
00177
00178
00179
00180 template <class T>
00181 class TropicalWeightTpl : public FloatWeightTpl<T> {
00182 public:
00183 using FloatWeightTpl<T>::Value;
00184
00185 typedef TropicalWeightTpl<T> ReverseWeight;
00186
00187 TropicalWeightTpl() : FloatWeightTpl<T>() {}
00188
00189 TropicalWeightTpl(T f) : FloatWeightTpl<T>(f) {}
00190
00191 TropicalWeightTpl(const TropicalWeightTpl<T> &w) : FloatWeightTpl<T>(w) {}
00192
00193 static const TropicalWeightTpl<T> Zero() {
00194 return TropicalWeightTpl<T>(FloatLimits<T>::kPosInfinity); }
00195
00196 static const TropicalWeightTpl<T> One() {
00197 return TropicalWeightTpl<T>(0.0F); }
00198
00199 static const string &Type() {
00200 static const string type = "tropical" +
00201 FloatWeightTpl<T>::GetPrecisionString();
00202 return type;
00203 }
00204
00205 bool Member() const {
00206
00207 return Value() == Value() && Value() != FloatLimits<T>::kNegInfinity;
00208 }
00209
00210 TropicalWeightTpl<T> Quantize(float delta = kDelta) const {
00211 if (Value() == FloatLimits<T>::kNegInfinity ||
00212 Value() == FloatLimits<T>::kPosInfinity ||
00213 Value() != Value())
00214 return *this;
00215 else
00216 return TropicalWeightTpl<T>(floor(Value()/delta + 0.5F) * delta);
00217 }
00218
00219 TropicalWeightTpl<T> Reverse() const { return *this; }
00220
00221 static uint64 Properties() {
00222 return kLeftSemiring | kRightSemiring | kCommutative |
00223 kPath | kIdempotent;
00224 }
00225 };
00226
00227
00228 typedef TropicalWeightTpl<float> TropicalWeight;
00229
00230 template <class T>
00231 inline TropicalWeightTpl<T> Plus(const TropicalWeightTpl<T> &w1,
00232 const TropicalWeightTpl<T> &w2) {
00233 return w1.Value() < w2.Value() ? w1 : w2;
00234 }
00235
00236 inline TropicalWeightTpl<float> Plus(const TropicalWeightTpl<float> &w1,
00237 const TropicalWeightTpl<float> &w2) {
00238 return Plus<float>(w1, w2);
00239 }
00240
00241 inline TropicalWeightTpl<double> Plus(const TropicalWeightTpl<double> &w1,
00242 const TropicalWeightTpl<double> &w2) {
00243 return Plus<double>(w1, w2);
00244 }
00245
00246 template <class T>
00247 inline TropicalWeightTpl<T> Times(const TropicalWeightTpl<T> &w1,
00248 const TropicalWeightTpl<T> &w2) {
00249 T f1 = w1.Value(), f2 = w2.Value();
00250 if (f1 == FloatLimits<T>::kPosInfinity)
00251 return w1;
00252 else if (f2 == FloatLimits<T>::kPosInfinity)
00253 return w2;
00254 else
00255 return TropicalWeightTpl<T>(f1 + f2);
00256 }
00257
00258 inline TropicalWeightTpl<float> Times(const TropicalWeightTpl<float> &w1,
00259 const TropicalWeightTpl<float> &w2) {
00260 return Times<float>(w1, w2);
00261 }
00262
00263 inline TropicalWeightTpl<double> Times(const TropicalWeightTpl<double> &w1,
00264 const TropicalWeightTpl<double> &w2) {
00265 return Times<double>(w1, w2);
00266 }
00267
00268 template <class T>
00269 inline TropicalWeightTpl<T> Divide(const TropicalWeightTpl<T> &w1,
00270 const TropicalWeightTpl<T> &w2,
00271 DivideType typ = DIVIDE_ANY) {
00272 T f1 = w1.Value(), f2 = w2.Value();
00273 if (f2 == FloatLimits<T>::kPosInfinity)
00274 return FloatLimits<T>::kNumberBad;
00275 else if (f1 == FloatLimits<T>::kPosInfinity)
00276 return FloatLimits<T>::kPosInfinity;
00277 else
00278 return TropicalWeightTpl<T>(f1 - f2);
00279 }
00280
00281 inline TropicalWeightTpl<float> Divide(const TropicalWeightTpl<float> &w1,
00282 const TropicalWeightTpl<float> &w2,
00283 DivideType typ = DIVIDE_ANY) {
00284 return Divide<float>(w1, w2, typ);
00285 }
00286
00287 inline TropicalWeightTpl<double> Divide(const TropicalWeightTpl<double> &w1,
00288 const TropicalWeightTpl<double> &w2,
00289 DivideType typ = DIVIDE_ANY) {
00290 return Divide<double>(w1, w2, typ);
00291 }
00292
00293
00294
00295 template <class T>
00296 class LogWeightTpl : public FloatWeightTpl<T> {
00297 public:
00298 using FloatWeightTpl<T>::Value;
00299
00300 typedef LogWeightTpl ReverseWeight;
00301
00302 LogWeightTpl() : FloatWeightTpl<T>() {}
00303
00304 LogWeightTpl(T f) : FloatWeightTpl<T>(f) {}
00305
00306 LogWeightTpl(const LogWeightTpl<T> &w) : FloatWeightTpl<T>(w) {}
00307
00308 static const LogWeightTpl<T> Zero() {
00309 return LogWeightTpl<T>(FloatLimits<T>::kPosInfinity);
00310 }
00311
00312 static const LogWeightTpl<T> One() {
00313 return LogWeightTpl<T>(0.0F);
00314 }
00315
00316 static const string &Type() {
00317 static const string type = "log" + FloatWeightTpl<T>::GetPrecisionString();
00318 return type;
00319 }
00320
00321 bool Member() const {
00322
00323 return Value() == Value() && Value() != FloatLimits<T>::kNegInfinity;
00324 }
00325
00326 LogWeightTpl<T> Quantize(float delta = kDelta) const {
00327 if (Value() == FloatLimits<T>::kNegInfinity ||
00328 Value() == FloatLimits<T>::kPosInfinity ||
00329 Value() != Value())
00330 return *this;
00331 else
00332 return LogWeightTpl<T>(floor(Value()/delta + 0.5F) * delta);
00333 }
00334
00335 LogWeightTpl<T> Reverse() const { return *this; }
00336
00337 static uint64 Properties() {
00338 return kLeftSemiring | kRightSemiring | kCommutative;
00339 }
00340 };
00341
00342
00343 typedef LogWeightTpl<float> LogWeight;
00344
00345 template <class T>
00346 inline T LogExp(T x) { return log(1.0F + exp(-x)); }
00347
00348 template <class T>
00349 inline LogWeightTpl<T> Plus(const LogWeightTpl<T> &w1,
00350 const LogWeightTpl<T> &w2) {
00351 T f1 = w1.Value(), f2 = w2.Value();
00352 if (f1 == FloatLimits<T>::kPosInfinity)
00353 return w2;
00354 else if (f2 == FloatLimits<T>::kPosInfinity)
00355 return w1;
00356 else if (f1 > f2)
00357 return LogWeightTpl<T>(f2 - LogExp(f1 - f2));
00358 else
00359 return LogWeightTpl<T>(f1 - LogExp(f2 - f1));
00360 }
00361
00362 inline LogWeightTpl<float> Plus(const LogWeightTpl<float> &w1,
00363 const LogWeightTpl<float> &w2) {
00364 return Plus<float>(w1, w2);
00365 }
00366
00367 inline LogWeightTpl<double> Plus(const LogWeightTpl<double> &w1,
00368 const LogWeightTpl<double> &w2) {
00369 return Plus<double>(w1, w2);
00370 }
00371
00372 template <class T>
00373 inline LogWeightTpl<T> Times(const LogWeightTpl<T> &w1,
00374 const LogWeightTpl<T> &w2) {
00375 T f1 = w1.Value(), f2 = w2.Value();
00376 if (f1 == FloatLimits<T>::kPosInfinity)
00377 return w1;
00378 else if (f2 == FloatLimits<T>::kPosInfinity)
00379 return w2;
00380 else
00381 return LogWeightTpl<T>(f1 + f2);
00382 }
00383
00384 inline LogWeightTpl<float> Times(const LogWeightTpl<float> &w1,
00385 const LogWeightTpl<float> &w2) {
00386 return Times<float>(w1, w2);
00387 }
00388
00389 inline LogWeightTpl<double> Times(const LogWeightTpl<double> &w1,
00390 const LogWeightTpl<double> &w2) {
00391 return Times<double>(w1, w2);
00392 }
00393
00394 template <class T>
00395 inline LogWeightTpl<T> Divide(const LogWeightTpl<T> &w1,
00396 const LogWeightTpl<T> &w2,
00397 DivideType typ = DIVIDE_ANY) {
00398 T f1 = w1.Value(), f2 = w2.Value();
00399 if (f2 == FloatLimits<T>::kPosInfinity)
00400 return FloatLimits<T>::kNumberBad;
00401 else if (f1 == FloatLimits<T>::kPosInfinity)
00402 return FloatLimits<T>::kPosInfinity;
00403 else
00404 return LogWeightTpl<T>(f1 - f2);
00405 }
00406
00407 inline LogWeightTpl<float> Divide(const LogWeightTpl<float> &w1,
00408 const LogWeightTpl<float> &w2,
00409 DivideType typ = DIVIDE_ANY) {
00410 return Divide<float>(w1, w2, typ);
00411 }
00412
00413 inline LogWeightTpl<double> Divide(const LogWeightTpl<double> &w1,
00414 const LogWeightTpl<double> &w2,
00415 DivideType typ = DIVIDE_ANY) {
00416 return Divide<double>(w1, w2, typ);
00417 }
00418
00419
00420 template <class T>
00421 class MinMaxWeightTpl : public FloatWeightTpl<T> {
00422 public:
00423 using FloatWeightTpl<T>::Value;
00424
00425 typedef MinMaxWeightTpl<T> ReverseWeight;
00426
00427 MinMaxWeightTpl() : FloatWeightTpl<T>() {}
00428
00429 MinMaxWeightTpl(T f) : FloatWeightTpl<T>(f) {}
00430
00431 MinMaxWeightTpl(const MinMaxWeightTpl<T> &w) : FloatWeightTpl<T>(w) {}
00432
00433 static const MinMaxWeightTpl<T> Zero() {
00434 return MinMaxWeightTpl<T>(FloatLimits<T>::kPosInfinity);
00435 }
00436
00437 static const MinMaxWeightTpl<T> One() {
00438 return MinMaxWeightTpl<T>(FloatLimits<T>::kNegInfinity);
00439 }
00440
00441 static const string &Type() {
00442 static const string type = "minmax" +
00443 FloatWeightTpl<T>::GetPrecisionString();
00444 return type;
00445 }
00446
00447 bool Member() const {
00448
00449 return Value() == Value();
00450 }
00451
00452 MinMaxWeightTpl<T> Quantize(float delta = kDelta) const {
00453
00454 if (Value() == FloatLimits<T>::kNegInfinity ||
00455 Value() == FloatLimits<T>::kPosInfinity ||
00456 Value() != Value())
00457 return *this;
00458 else
00459 return MinMaxWeightTpl<T>(floor(Value()/delta + 0.5F) * delta);
00460 }
00461
00462 MinMaxWeightTpl<T> Reverse() const { return *this; }
00463
00464 static uint64 Properties() {
00465 return kLeftSemiring | kRightSemiring | kCommutative | kIdempotent | kPath;
00466 }
00467 };
00468
00469
00470 typedef MinMaxWeightTpl<float> MinMaxWeight;
00471
00472
00473 template <class T>
00474 inline MinMaxWeightTpl<T> Plus(
00475 const MinMaxWeightTpl<T> &w1, const MinMaxWeightTpl<T> &w2) {
00476 return w1.Value() < w2.Value() ? w1 : w2;
00477 }
00478
00479 inline MinMaxWeightTpl<float> Plus(
00480 const MinMaxWeightTpl<float> &w1, const MinMaxWeightTpl<float> &w2) {
00481 return Plus<float>(w1, w2);
00482 }
00483
00484 inline MinMaxWeightTpl<double> Plus(
00485 const MinMaxWeightTpl<double> &w1, const MinMaxWeightTpl<double> &w2) {
00486 return Plus<double>(w1, w2);
00487 }
00488
00489
00490 template <class T>
00491 inline MinMaxWeightTpl<T> Times(
00492 const MinMaxWeightTpl<T> &w1, const MinMaxWeightTpl<T> &w2) {
00493 return w1.Value() >= w2.Value() ? w1 : w2;
00494 }
00495
00496 inline MinMaxWeightTpl<float> Times(
00497 const MinMaxWeightTpl<float> &w1, const MinMaxWeightTpl<float> &w2) {
00498 return Times<float>(w1, w2);
00499 }
00500
00501 inline MinMaxWeightTpl<double> Times(
00502 const MinMaxWeightTpl<double> &w1, const MinMaxWeightTpl<double> &w2) {
00503 return Times<double>(w1, w2);
00504 }
00505
00506
00507 template <class T>
00508 inline MinMaxWeightTpl<T> Divide(const MinMaxWeightTpl<T> &w1,
00509 const MinMaxWeightTpl<T> &w2,
00510 DivideType typ = DIVIDE_ANY) {
00511
00512 return w1.Value() >= w2.Value() ? w1 : FloatLimits<T>::kNumberBad;
00513 }
00514
00515 inline MinMaxWeightTpl<float> Divide(const MinMaxWeightTpl<float> &w1,
00516 const MinMaxWeightTpl<float> &w2,
00517 DivideType typ = DIVIDE_ANY) {
00518 return Divide<float>(w1, w2, typ);
00519 }
00520
00521 inline MinMaxWeightTpl<double> Divide(const MinMaxWeightTpl<double> &w1,
00522 const MinMaxWeightTpl<double> &w2,
00523 DivideType typ = DIVIDE_ANY) {
00524 return Divide<double>(w1, w2, typ);
00525 }
00526
00527
00528 }
00529
00530 #endif /// FST_LIB_FLOAT_WEIGHT_H__
00531