20 #ifndef FST_FLOAT_WEIGHT_H_ 21 #define FST_FLOAT_WEIGHT_H_ 37 #include <type_traits> 43 #include <string_view> 52 inline constexpr
bool IsNan(T value) {
53 return value != value;
62 return std::numeric_limits<T>::infinity();
67 static constexpr T
NumberBad() {
return std::numeric_limits<T>::quiet_NaN(); }
71 template <
class T =
float>
80 std::istream &
Read(std::istream &strm) {
return ReadType(strm, &value_); }
82 std::ostream &
Write(std::ostream &strm)
const {
92 std::memcpy(&hash, &value_, std::min(
sizeof(hash),
sizeof(value_)));
96 constexpr
const T &
Value()
const {
return value_; }
102 return sizeof(T) == 4 ?
"" 103 :
sizeof(T) == 1 ?
"8" 104 :
sizeof(T) == 2 ?
"16" 105 :
sizeof(T) == 8 ?
"64" 119 #if (defined(__i386__) || defined(__x86_64__)) && !defined(__SSE2_MATH__) 124 #error "Please compile with -msse -mfpmath=sse, or equivalent." 135 return operator==<
float>(w1, w2);
140 return operator==<
double>(w1, w2);
151 return operator!=<
float>(w1, w2);
156 return operator!=<
double>(w1, w2);
161 return w1 <= w2 + delta && w2 <= w1 + delta;
174 return strm <<
"Infinity";
176 return strm <<
"-Infinity";
178 return strm <<
"BadNumber";
180 return strm << w.
Value();
188 if (s ==
"Infinity") {
190 }
else if (s ==
"-Infinity") {
194 T f = strtod(s.c_str(), &p);
195 if (p < s.c_str() + s.size()) {
196 strm.clear(std::ios::badbit);
222 return Limits::NumberBad();
225 static const std::string &
Type() {
226 static const std::string *
const type =
new std::string(
249 return Limits::NegInfinity() < Value();
253 if (!Member() || Value() == Limits::PosInfinity()) {
282 return Plus<float>(w1, w2);
287 return Plus<double>(w1, w2);
317 return Times<float>(w1, w2);
322 return Times<double>(w1, w2);
359 return Divide<float>(w1, w2, typ);
365 return Divide<double>(w1, w2, typ);
399 template <
class T,
class V,
bool Enable = !std::is_same_v<V,
size_t>,
400 typename std::enable_if_t<Enable> * =
nullptr>
404 : (n == 0 || w == Weight::One()) ? Weight::One()
405 : Weight(w.
Value() * n);
414 return Power<float, size_t, true>(weight, n);
420 return Power<double, size_t, true>(weight, n);
442 static const std::string &
Type() {
443 static const std::string *
const type =
new std::string(
450 return Limits::NegInfinity() < Value();
454 if (!Member() || Value() == Limits::PosInfinity()) {
479 return log1p(exp(-x));
485 return log1p(-exp(-x));
518 const T f1 = w1.
Value();
519 const T f2 = w2.
Value();
520 if (f1 == Limits::PosInfinity()) {
522 }
else if (f2 == Limits::PosInfinity()) {
524 }
else if (f1 > f2) {
533 return Plus<float>(w1, w2);
538 return Plus<double>(w1, w2);
546 const T f1 = w1.
Value();
547 const T f2 = w2.
Value();
549 if (f2 == Limits::PosInfinity())
return f1;
551 if (d == Limits::PosInfinity())
return f1;
557 return Minus<float>(w1, w2);
562 return Minus<double>(w1, w2);
574 return Times<float>(w1, w2);
579 return Times<double>(w1, w2);
594 return Divide<float>(w1, w2, typ);
600 return Divide<double>(w1, w2, typ);
605 template <
class T,
class V,
bool Enable = !std::is_same_v<V,
size_t>,
606 typename std::enable_if_t<Enable> * =
nullptr>
610 : (n == 0 || w == Weight::One()) ? Weight::One()
611 : Weight(w.
Value() * n);
620 return Power<float, size_t, true>(weight, n);
626 return Power<double, size_t, true>(weight, n);
635 explicit Adder(
Weight w = Weight::Zero()) : sum_(w.Value()), c_(0.0) {}
639 const T f = w.
Value();
640 if (f == Limits::PosInfinity()) {
642 }
else if (sum_ == Limits::PosInfinity()) {
645 }
else if (f > sum_) {
684 static const std::string &
Type() {
685 static const std::string *
const type =
new std::string(
692 return Limits::NegInfinity() < Value();
696 if (!Member() || Value() == Limits::PosInfinity()) {
734 const T f1 = w1.
Value();
735 const T f2 = w2.
Value();
741 return Plus<float>(w1, w2);
746 return Plus<double>(w1, w2);
753 const T f1 = w1.
Value();
754 const T f2 = w2.
Value();
760 return Minus<float>(w1, w2);
765 return Minus<double>(w1, w2);
777 return Times<float>(w1, w2);
782 return Times<double>(w1, w2);
796 return Divide<float>(w1, w2, typ);
802 return Divide<double>(w1, w2, typ);
807 template <
class T,
class V,
bool Enable = !std::is_same_v<V,
size_t>,
808 typename std::enable_if_t<Enable> * =
nullptr>
812 : (n == 0 || w == Weight::One()) ? Weight::One()
813 : Weight(pow(w.
Value(), n));
822 return Power<float, size_t, true>(weight, n);
828 return Power<double, size_t, true>(weight, n);
837 explicit Adder(
Weight w = Weight::Zero()) : sum_(w.Value()), c_(0.0) {}
841 const T f = w.
Value();
842 if (f == Limits::PosInfinity()) {
844 }
else if (sum_ == Limits::PosInfinity()) {
883 static const std::string &
Type() {
884 static const std::string *
const type =
new std::string(
894 if (!Member() || Value() == Limits::NegInfinity() ||
895 Value() == Limits::PosInfinity()) {
923 return Plus<float>(w1, w2);
928 return Plus<double>(w1, w2);
942 return Times<float>(w1, w2);
947 return Times<double>(w1, w2);
961 return Divide<float>(w1, w2, typ);
967 return Divide<double>(w1, w2, typ);
1026 return -log(w.
Value());
1064 return exp(-w.
Value());
1079 template <
class Weight>
1083 uint64_t seed = std::random_device()(),
bool allow_zero =
true,
1086 allow_zero_(allow_zero),
1087 num_random_weights_(num_random_weights) {}
1090 const int sample = std::uniform_int_distribution<>(
1091 0, num_random_weights_ + allow_zero_ - 1)(rand_);
1092 if (allow_zero_ && sample == num_random_weights_)
return Weight::Zero();
1093 return Weight(sample);
1097 mutable std::mt19937_64 rand_;
1098 const bool allow_zero_;
1099 const size_t num_random_weights_;
1110 bool allow_zero =
true,
1112 :
Generate(seed, allow_zero, num_random_weights) {}
1125 bool allow_zero =
true,
1127 :
Generate(seed, allow_zero, num_random_weights) {}
1140 bool allow_zero =
true,
1142 :
Generate(seed, allow_zero, num_random_weights) {}
1157 bool allow_zero =
true,
1160 allow_zero_(allow_zero),
1161 num_random_weights_(num_random_weights) {}
1164 const int sample = std::uniform_int_distribution<>(
1165 -num_random_weights_, num_random_weights_ + allow_zero_)(rand_);
1166 if (allow_zero_ && sample == 0) {
1167 return Weight::Zero();
1168 }
else if (sample == -num_random_weights_) {
1169 return Weight::One();
1176 mutable std::mt19937_64 rand_;
1177 const bool allow_zero_;
1178 const size_t num_random_weights_;
1183 #endif // FST_FLOAT_WEIGHT_H_ RealWeight operator()(const Log64Weight &w) const
WeightGenerate(uint64_t seed=std::random_device()(), bool allow_zero=true, size_t num_random_weights=kNumRandomWeights)
Weight Add(const Weight &w)
static constexpr RealWeightTpl Zero()
void Reset(Weight w=Weight::Zero())
static constexpr TropicalWeightTpl< T > Zero()
constexpr TropicalWeight operator()(const LogWeight &w) const
FloatWeightGenerate(uint64_t seed=std::random_device()(), bool allow_zero=true, const size_t num_random_weights=kNumRandomWeights)
constexpr RealWeight operator()(const Real64Weight &w) const
constexpr Log64Weight operator()(const LogWeight &w) const
ErrorWeight Plus(const ErrorWeight &, const ErrorWeight &)
WeightGenerate(uint64_t seed=std::random_device()(), bool allow_zero=true, size_t num_random_weights=kNumRandomWeights)
constexpr bool Member() const
Adder(Weight w=Weight::Zero())
RealWeight operator()(const LogWeight &w) const
ErrorWeight Times(const ErrorWeight &, const ErrorWeight &)
static constexpr std::string_view GetPrecisionString()
RealWeightTpl< T > Quantize(float delta=kDelta) const
static constexpr LogWeightTpl Zero()
static constexpr MinMaxWeightTpl NoWeight()
static constexpr MinMaxWeightTpl One()
constexpr uint64_t kIdempotent
std::ostream & Write(std::ostream &strm) const
Weight operator()() const
constexpr Log64Weight operator()(const TropicalWeight &w) const
void SetValue(const T &f)
static constexpr uint64_t Properties()
WeightGenerate(uint64_t seed=std::random_device()(), bool allow_zero=true, size_t num_random_weights=kNumRandomWeights)
static constexpr T PosInfinity()
constexpr RealWeightTpl< T > Reverse() const
static constexpr uint64_t Properties()
TropicalWeightTpl< T > Quantize(float delta=kDelta) const
constexpr uint64_t kRightSemiring
std::ostream & WriteType(std::ostream &strm, const T t)
static constexpr LogWeightTpl One()
static constexpr TropicalWeightTpl< T > One()
constexpr bool FloatApproxEqual(T w1, T w2, float delta=kDelta)
static constexpr T NumberBad()
std::istream & operator>>(std::istream &strm, FloatWeightTpl< T > &w)
Log64Weight operator()(const Real64Weight &w) const
Real64Weight operator()(const LogWeight &w) const
constexpr bool IsNan(T value)
constexpr TropicalWeightTpl< T > Reverse() const
bool operator!=(const ErrorWeight &, const ErrorWeight &)
constexpr LogWeight operator()(const TropicalWeight &w) const
MinMaxWeightTpl< T > Quantize(float delta=kDelta) const
Weight operator()() const
static constexpr LogWeightTpl NoWeight()
constexpr uint64_t kCommutative
std::ostream & operator<<(std::ostream &strm, const ErrorWeight &)
LogWeight operator()(const RealWeight &w) const
Adder(Weight w=Weight::Zero())
void Reset(Weight w=Weight::Zero())
constexpr MinMaxWeightTpl(T f)
static constexpr RealWeightTpl NoWeight()
static const std::string & Type()
Weight operator()() const
LogWeightTpl< T > Quantize(float delta=kDelta) const
static constexpr TropicalWeightTpl< T > NoWeight()
static constexpr uint64_t Properties()
static constexpr RealWeightTpl One()
constexpr LogWeightTpl< T > Reverse() const
double LogPosExp(double x)
double KahanLogSum(double a, double b, double *c)
TropicalWeightTpl() noexcept
LogWeight operator()(const Real64Weight &w) const
std::istream & Read(std::istream &strm)
Weight operator()() const
static const std::string & Type()
Log64Weight operator()(const RealWeight &w) const
Weight Add(const Weight &w)
constexpr bool Member() const
double LogNegExp(double x)
constexpr RealWeightTpl(T f)
MinMaxWeightTpl() noexcept
LogWeightTpl< T > Minus(const LogWeightTpl< T > &w1, const LogWeightTpl< T > &w2)
constexpr bool Member() const
std::string StrCat(const StringOrInt &s1, const StringOrInt &s2)
static const std::string & Type()
constexpr bool Member() const
ErrorWeight Divide(const ErrorWeight &, const ErrorWeight &)
bool operator==(const ErrorWeight &, const ErrorWeight &)
constexpr size_t kNumRandomWeights
static constexpr MinMaxWeightTpl Zero()
constexpr TropicalWeight operator()(const Log64Weight &w) const
static const std::string & Type()
std::istream & ReadType(std::istream &strm, T *t)
constexpr MinMaxWeightTpl< T > Reverse() const
static constexpr uint64_t Properties()
constexpr TropicalWeightTpl< T > Power(const TropicalWeightTpl< T > &w, V n)
constexpr LogWeight operator()(const Log64Weight &w) const
Weight operator()() const
constexpr uint64_t kLeftSemiring
constexpr Real64Weight operator()(const RealWeight &w) const
WeightGenerate(uint64_t seed=std::random_device()(), bool allow_zero=true, size_t num_random_weights=kNumRandomWeights)
Real64Weight operator()(const Log64Weight &w) const
constexpr const T & Value() const
bool ApproxEqual(const ErrorWeight &, const ErrorWeight &, float)
constexpr LogWeightTpl(T f)
constexpr TropicalWeightTpl(T f)
double KahanLogDiff(double a, double b, double *c)
static constexpr T NegInfinity()
double KahanRealSum(double a, double b, double *c)