20 #ifndef FST_FLOAT_WEIGHT_H_ 21 #define FST_FLOAT_WEIGHT_H_ 37 #include <type_traits> 43 #include <string_view> 51 inline constexpr
bool IsNan(T value) {
52 return value != value;
61 return std::numeric_limits<T>::infinity();
66 static constexpr T
NumberBad() {
return std::numeric_limits<T>::quiet_NaN(); }
70 template <
class T =
float>
79 std::istream &
Read(std::istream &strm) {
return ReadType(strm, &value_); }
81 std::ostream &
Write(std::ostream &strm)
const {
91 std::memcpy(&hash, &value_, std::min(
sizeof(hash),
sizeof(value_)));
95 constexpr
const T &
Value()
const {
return value_; }
101 return sizeof(T) == 4 ?
"" 102 :
sizeof(T) == 1 ?
"8" 103 :
sizeof(T) == 2 ?
"16" 104 :
sizeof(T) == 8 ?
"64" 118 #if (defined(__i386__) || defined(__x86_64__)) && !defined(__SSE2_MATH__) 123 #error "Please compile with -msse -mfpmath=sse, or equivalent." 134 return operator==<
float>(w1, w2);
139 return operator==<
double>(w1, w2);
150 return operator!=<
float>(w1, w2);
155 return operator!=<
double>(w1, w2);
160 return w1 <= w2 + delta && w2 <= w1 + delta;
173 return strm <<
"Infinity";
175 return strm <<
"-Infinity";
177 return strm <<
"BadNumber";
179 return strm << w.
Value();
187 if (s ==
"Infinity") {
189 }
else if (s ==
"-Infinity") {
193 T f = strtod(s.c_str(), &p);
194 if (p < s.c_str() + s.size()) {
195 strm.clear(std::ios::badbit);
221 return Limits::NumberBad();
224 static const std::string &
Type() {
225 static const std::string *
const type =
new std::string(
248 return Limits::NegInfinity() < Value();
252 if (!Member() || Value() == Limits::PosInfinity()) {
281 return Plus<float>(w1, w2);
286 return Plus<double>(w1, w2);
316 return Times<float>(w1, w2);
321 return Times<double>(w1, w2);
358 return Divide<float>(w1, w2, typ);
364 return Divide<double>(w1, w2, typ);
398 template <
class T,
class V,
bool Enable = !std::is_same_v<V,
size_t>,
399 typename std::enable_if_t<Enable> * =
nullptr>
403 : (n == 0 || w == Weight::One()) ? Weight::One()
404 : Weight(w.
Value() * n);
413 return Power<float, size_t, true>(weight, n);
419 return Power<double, size_t, true>(weight, n);
441 static const std::string &
Type() {
442 static const std::string *
const type =
new std::string(
449 return Limits::NegInfinity() < Value();
453 if (!Member() || Value() == Limits::PosInfinity()) {
478 return log1p(exp(-x));
484 return log1p(-exp(-x));
517 const T f1 = w1.
Value();
518 const T f2 = w2.
Value();
519 if (f1 == Limits::PosInfinity()) {
521 }
else if (f2 == Limits::PosInfinity()) {
523 }
else if (f1 > f2) {
532 return Plus<float>(w1, w2);
537 return Plus<double>(w1, w2);
545 const T f1 = w1.
Value();
546 const T f2 = w2.
Value();
548 if (f2 == Limits::PosInfinity())
return f1;
550 if (d == Limits::PosInfinity())
return f1;
556 return Minus<float>(w1, w2);
561 return Minus<double>(w1, w2);
573 return Times<float>(w1, w2);
578 return Times<double>(w1, w2);
593 return Divide<float>(w1, w2, typ);
599 return Divide<double>(w1, w2, typ);
604 template <
class T,
class V,
bool Enable = !std::is_same_v<V,
size_t>,
605 typename std::enable_if_t<Enable> * =
nullptr>
609 : (n == 0 || w == Weight::One()) ? Weight::One()
610 : Weight(w.
Value() * n);
619 return Power<float, size_t, true>(weight, n);
625 return Power<double, size_t, true>(weight, n);
634 explicit Adder(
Weight w = Weight::Zero()) : sum_(w.Value()), c_(0.0) {}
638 const T f = w.
Value();
639 if (f == Limits::PosInfinity()) {
641 }
else if (sum_ == Limits::PosInfinity()) {
644 }
else if (f > sum_) {
683 static const std::string &
Type() {
684 static const std::string *
const type =
new std::string(
691 return Limits::NegInfinity() < Value();
695 if (!Member() || Value() == Limits::PosInfinity()) {
733 const T f1 = w1.
Value();
734 const T f2 = w2.
Value();
740 return Plus<float>(w1, w2);
745 return Plus<double>(w1, w2);
752 const T f1 = w1.
Value();
753 const T f2 = w2.
Value();
759 return Minus<float>(w1, w2);
764 return Minus<double>(w1, w2);
776 return Times<float>(w1, w2);
781 return Times<double>(w1, w2);
795 return Divide<float>(w1, w2, typ);
801 return Divide<double>(w1, w2, typ);
806 template <
class T,
class V,
bool Enable = !std::is_same_v<V,
size_t>,
807 typename std::enable_if_t<Enable> * =
nullptr>
811 : (n == 0 || w == Weight::One()) ? Weight::One()
812 : Weight(pow(w.
Value(), n));
821 return Power<float, size_t, true>(weight, n);
827 return Power<double, size_t, true>(weight, n);
836 explicit Adder(
Weight w = Weight::Zero()) : sum_(w.Value()), c_(0.0) {}
840 const T f = w.
Value();
841 if (f == Limits::PosInfinity()) {
843 }
else if (sum_ == Limits::PosInfinity()) {
882 static const std::string &
Type() {
883 static const std::string *
const type =
new std::string(
893 if (!Member() || Value() == Limits::NegInfinity() ||
894 Value() == Limits::PosInfinity()) {
922 return Plus<float>(w1, w2);
927 return Plus<double>(w1, w2);
941 return Times<float>(w1, w2);
946 return Times<double>(w1, w2);
960 return Divide<float>(w1, w2, typ);
966 return Divide<double>(w1, w2, typ);
1025 return -log(w.
Value());
1063 return exp(-w.
Value());
1078 template <
class Weight>
1082 uint64_t seed = std::random_device()(),
bool allow_zero =
true,
1085 allow_zero_(allow_zero),
1086 num_random_weights_(num_random_weights) {}
1089 const int sample = std::uniform_int_distribution<>(
1090 0, num_random_weights_ + allow_zero_ - 1)(rand_);
1091 if (allow_zero_ && sample == num_random_weights_)
return Weight::Zero();
1092 return Weight(sample);
1096 mutable std::mt19937_64 rand_;
1097 const bool allow_zero_;
1098 const size_t num_random_weights_;
1109 bool allow_zero =
true,
1111 :
Generate(seed, allow_zero, num_random_weights) {}
1124 bool allow_zero =
true,
1126 :
Generate(seed, allow_zero, num_random_weights) {}
1139 bool allow_zero =
true,
1141 :
Generate(seed, allow_zero, num_random_weights) {}
1156 bool allow_zero =
true,
1159 allow_zero_(allow_zero),
1160 num_random_weights_(num_random_weights) {}
1163 const int sample = std::uniform_int_distribution<>(
1164 -num_random_weights_, num_random_weights_ + allow_zero_)(rand_);
1165 if (allow_zero_ && sample == 0) {
1166 return Weight::Zero();
1167 }
else if (sample == -num_random_weights_) {
1168 return Weight::One();
1175 mutable std::mt19937_64 rand_;
1176 const bool allow_zero_;
1177 const size_t num_random_weights_;
1182 #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)