00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00017 #ifndef BOOST_LIKELIHOODS_HPP
00018 #define BOOST_LIKELIHOODS_HPP
00019
00020 #include <cmath>
00021 #include <limits>
00022 #include <boost/concept_check.hpp>
00023 #include <boost/operators.hpp>
00024 #include <boost/probabilities.hpp>
00025
00026 namespace boost
00027 {
00028
00029 namespace probabilities
00030 {
00031
00068 template < typename Domain = linear_domain, typename Value = double,
00069 typename Validator = null_validator<Value> >
00070 class likelihood
00071 : boost::multiplicative<likelihood<Domain,Value,Validator>
00072 , boost::multiplicative2<likelihood<Domain,Value,Validator>,Value
00073 , boost::multiplicative2<likelihood<Domain,Value,Validator>,
00074 probability<Domain,Value,Validator>
00075 , boost::totally_ordered<likelihood<Domain,Value,Validator>
00076 , boost::totally_ordered2<likelihood<Domain,Value,Validator>,Value
00077 , boost::totally_ordered2<likelihood<Domain,Value,Validator>,
00078 probability<Domain,Value,Validator>
00079 > > > > > >
00080 {
00081 public:
00088 typedef Domain domain_type;
00095 typedef Value value_type;
00097 typedef Validator validator_type;
00098
00099 private:
00100 BOOST_CLASS_REQUIRE(value_type, boost, AssignableConcept);
00101 BOOST_CLASS_REQUIRE(value_type, boost, CopyConstructibleConcept);
00102 BOOST_CLASS_REQUIRE(value_type, boost, EqualityComparableConcept);
00103 BOOST_CLASS_REQUIRE(value_type, boost, ComparableConcept);
00104 BOOST_CLASS_REQUIRE(validator_type, probabilities, ValidatorConcept);
00105
00106 public:
00115 likelihood ()
00116 : l_(domain_traits<likelihood_tag,domain_type,value_type>::
00117 default_value())
00118 { validator_type::is_valid(l_,domain_type()); }
00127 template <typename T>
00128 explicit likelihood (const T& t)
00129 : l_(t)
00130 {
00131 function_requires< ConvertibleConcept<T,value_type> >();
00132 validator_type::is_valid(l_,domain_type());
00133 }
00142 template <typename T, typename D>
00143 likelihood (const T& t, D)
00144 : l_(domain_traits<likelihood_tag,domain_type,value_type>::
00145 transform_domain(D(),t))
00146 {
00147 function_requires< ConvertibleConcept<T,value_type> >();
00148 validator_type::is_valid(l_,domain_type());
00149 }
00151 template <typename D, typename V, typename VV>
00152 likelihood (const likelihood<D,V,VV>& l)
00153 : l_(l.value_cast(domain_type()))
00154 {
00155 function_requires< ConvertibleConcept<V,value_type> >();
00156 validator_type::is_valid(l_,domain_type());
00157 }
00161 template <typename D, typename V, typename VV>
00162 likelihood (const probability<D,V,VV>& l)
00163 : l_(l.value_cast(domain_type()))
00164 {
00165 function_requires< ConvertibleConcept<V,value_type> >();
00166 validator_type::is_valid(l_,domain_type());
00167 }
00168 likelihood (const likelihood& l) : l_(l.l_) { }
00169 ~likelihood () { }
00170 likelihood& operator = (const likelihood& l)
00171 { likelihood l_(l); swap(l_); return *this; }
00172 void swap (likelihood& l) { std::swap (l_, l.l_); }
00173
00184
00185 template <typename D,typename V, typename VV>
00186 likelihood& operator += (const likelihood<D,V,VV>& l)
00187 {
00188 function_requires< ConvertibleConcept<V,value_type> >();
00189 domain_traits<likelihood_tag,domain_type,value_type>::assign_add
00190 (l_,value_type(l.value_cast(domain_type())));
00191 validator_type::is_valid(l_,domain_type());
00192 return *this;
00193 }
00202 template <typename T>
00203 likelihood& operator += (const T& t)
00204 {
00205 function_requires< ConvertibleConcept<T,value_type> >();
00206 value_type domain_t
00207 (domain_traits<likelihood_tag,domain_type,value_type>::
00208 transform_domain(linear_domain(),t));
00209 domain_traits<likelihood_tag,domain_type,value_type>::
00210 assign_add(l_,domain_t);
00211 validator_type::is_valid(l_,domain_type());
00212 return *this;
00213 }
00215 template <typename D, typename V, typename VV>
00216 likelihood& operator += (const probability<D,V,VV>& p)
00217 {
00218 function_requires< ConvertibleConcept<V,value_type> >();
00219 domain_traits<likelihood_tag,domain_type,value_type>::assign_add
00220 (l_,value_type(p.value_cast(domain_type())));
00221 validator_type::is_valid(l_,domain_type());
00222 return *this;
00223 }
00224
00226 template <typename D, typename V, typename VV>
00227 likelihood& operator -= (const likelihood<D,V,VV>& l)
00228 {
00229 function_requires< ConvertibleConcept<V,value_type> >();
00230 domain_traits<likelihood_tag,domain_type,value_type>::assign_sub
00231 (l_,value_type(l.value_cast(domain_type())));
00232 validator_type::is_valid(l_,domain_type());
00233 return *this;
00234 }
00243 template <typename T>
00244 likelihood& operator -= (const T& t)
00245 {
00246 function_requires< ConvertibleConcept<T,value_type> >();
00247 value_type domain_t
00248 (domain_traits<likelihood_tag,domain_type,value_type>::
00249 transform_domain(linear_domain(),t));
00250 domain_traits<likelihood_tag,domain_type,value_type>::
00251 assign_sub(l_,domain_t);
00252 validator_type::is_valid(l_,domain_type());
00253 return *this;
00254 }
00256 template <typename D, typename V, typename VV>
00257 likelihood& operator -= (const probability<D,V,VV>& p)
00258 {
00259 function_requires< ConvertibleConcept<V,value_type> >();
00260 domain_traits<likelihood_tag,domain_type,value_type>::assign_sub
00261 (l_,value_type(p.value_cast(domain_type())));
00262 validator_type::is_valid(l_,domain_type());
00263 return *this;
00264 }
00265
00267 template <typename D, typename V, typename VV>
00268 likelihood& operator *= (const likelihood<D,V,VV>& l)
00269 {
00270 function_requires< ConvertibleConcept<V,value_type> >();
00271 domain_traits<likelihood_tag,domain_type,value_type>::assign_mpy
00272 (l_,value_type(l.value_cast(domain_type())));
00273 validator_type::is_valid(l_,domain_type());
00274 return *this;
00275 }
00284 template <typename T>
00285 likelihood& operator *= (const T& t)
00286 {
00287 function_requires< ConvertibleConcept<T,value_type> >();
00288 value_type domain_t
00289 (domain_traits<likelihood_tag,domain_type,value_type>::
00290 transform_domain(linear_domain(),t));
00291 domain_traits<likelihood_tag,domain_type,value_type>::
00292 assign_mpy(l_,domain_t);
00293 validator_type::is_valid(l_,domain_type());
00294 return *this;
00295 }
00297 template <typename D, typename V, typename VV>
00298 likelihood& operator *= (const probability<D,V,VV>& p)
00299 {
00300 function_requires< ConvertibleConcept<V,value_type> >();
00301 domain_traits<likelihood_tag,domain_type,value_type>::assign_mpy
00302 (l_,value_type(p.value_cast(domain_type())));
00303 validator_type::is_valid(l_,domain_type());
00304 return *this;
00305 }
00306
00308 template <typename D, typename V, typename VV>
00309 likelihood& operator /= (const likelihood<D,V,VV>& l)
00310 {
00311 function_requires< ConvertibleConcept<V,value_type> >();
00312 domain_traits<likelihood_tag,domain_type,value_type>::assign_div
00313 (l_,value_type(l.value_cast(domain_type())));
00314 validator_type::is_valid(l_,domain_type());
00315 return *this;
00316 }
00325 template <typename T>
00326 likelihood& operator /= (const T& t)
00327 {
00328 function_requires< ConvertibleConcept<T,value_type> >();
00329 value_type domain_t
00330 (domain_traits<likelihood_tag,domain_type,value_type>::
00331 transform_domain(linear_domain(),t));
00332 domain_traits<likelihood_tag,domain_type,value_type>::
00333 assign_div(l_,domain_t);
00334 validator_type::is_valid(l_,domain_type());
00335 return *this;
00336 }
00338 template <typename D, typename V, typename VV>
00339 likelihood& operator /= (const probability<D,V,VV>& p)
00340 {
00341 function_requires< ConvertibleConcept<V,value_type> >();
00342 domain_traits<likelihood_tag,domain_type,value_type>::assign_div
00343 (l_,value_type(p.value_cast(domain_type())));
00344 validator_type::is_valid(l_,domain_type());
00345 return *this;
00346 }
00348
00350 likelihood operator + () const { return *this; }
00351
00353 template <typename D>
00354 likelihood<D,value_type,validator_type> domain_cast (D) const
00355 { return likelihood<D,value_type,validator_type>(value_cast(D())); }
00356
00358 template <typename D>
00359 value_type value_cast (D) const
00360 {
00361 return domain_traits<likelihood_tag,D,value_type>::
00362 transform_domain(domain_type(),l_);
00363 }
00364
00365 private:
00366 value_type l_;
00367 };
00368
00370
00371
00381 template <typename TargetDomain, typename SourceDomain,
00382 typename Value, typename Validator>
00383 likelihood<TargetDomain,Value,Validator>
00384 domain_cast (const likelihood<SourceDomain,Value,Validator>& l)
00385 { return l.domain_cast (TargetDomain()); }
00386
00401 template <typename TargetDomain, typename SourceDomain,
00402 typename Value, typename Validator>
00403 typename likelihood<TargetDomain,Value,Validator>::value_type
00404 value_cast (const likelihood<SourceDomain,Value,Validator>& l)
00405 { return l.value_cast(TargetDomain()); }
00407
00409
00410
00411 template <typename Ldomain, typename Lvalue, typename Lvalidator,
00412 typename Rdomain, typename Rvalue, typename Rvalidator>
00413 likelihood<Ldomain, Lvalue, Lvalidator>
00414 operator + (const likelihood<Ldomain,Lvalue,Lvalidator>& lhs,
00415 const likelihood<Rdomain,Rvalue,Rvalidator>& rhs)
00416 {
00417 likelihood<Ldomain,Lvalue,Lvalidator> l(lhs);
00418 l += rhs;
00419 return l;
00420 }
00422 template <typename Ldomain, typename Lvalue, typename Lvalidator,
00423 typename Rdomain, typename Rvalue, typename Rvalidator>
00424 likelihood<Ldomain, Lvalue, Lvalidator>
00425 operator + (const likelihood<Ldomain,Lvalue,Lvalidator>& lhs,
00426 const probability<Rdomain,Rvalue,Rvalidator>& rhs)
00427 {
00428 likelihood<Ldomain,Lvalue,Lvalidator> l(lhs);
00429 l += rhs;
00430 return l;
00431 }
00433 template <typename Ldomain, typename Lvalue, typename Lvalidator,
00434 typename Rdomain, typename Rvalue, typename Rvalidator>
00435 likelihood<Ldomain, Lvalue, Lvalidator>
00436 operator + (const probability<Ldomain,Lvalue,Lvalidator>& lhs,
00437 const likelihood<Rdomain,Rvalue,Rvalidator>& rhs)
00438 {
00439 likelihood<Ldomain,Lvalue,Lvalidator> l(lhs);
00440 l += rhs;
00441 return l;
00442 }
00443
00445 template <typename Ldomain, typename Lvalue, typename Lvalidator,
00446 typename Rdomain, typename Rvalue, typename Rvalidator>
00447 likelihood<Ldomain, Lvalue, Lvalidator>
00448 operator - (const likelihood<Ldomain,Lvalue,Lvalidator>& lhs,
00449 const likelihood<Rdomain,Rvalue,Rvalidator>& rhs)
00450 {
00451 likelihood<Ldomain,Lvalue,Lvalidator> l(lhs);
00452 l -= rhs;
00453 return l;
00454 }
00455
00457 template <typename Ldomain, typename Lvalue, typename Lvalidator,
00458 typename Rdomain, typename Rvalue, typename Rvalidator>
00459 likelihood<log_domain, Lvalue, Lvalidator>
00460 operator * (const likelihood<Ldomain,Lvalue,Lvalidator>& lhs,
00461 const likelihood<Rdomain,Rvalue,Rvalidator>& rhs)
00462 {
00463 likelihood<log_domain, Lvalue, Lvalidator> p(lhs);
00464 p *= rhs;
00465 return p;
00466 }
00468 template <typename Ldomain, typename Lvalue, typename Lvalidator,
00469 typename Rdomain, typename Rvalue, typename Rvalidator>
00470 likelihood<log_domain, Lvalue, Lvalidator>
00471 operator * (const likelihood<Ldomain,Lvalue,Lvalidator>& lhs,
00472 const probability<Rdomain,Rvalue,Rvalidator>& rhs)
00473 {
00474 likelihood<log_domain, Lvalue, Lvalidator> p(lhs);
00475 p *= rhs;
00476 return p;
00477 }
00479 template <typename Ldomain, typename Lvalue, typename Lvalidator,
00480 typename Rdomain, typename Rvalue, typename Rvalidator>
00481 likelihood<log_domain, Lvalue, Lvalidator>
00482 operator * (const probability<Ldomain,Lvalue,Lvalidator>& lhs,
00483 const likelihood<Rdomain,Rvalue,Rvalidator>& rhs)
00484 {
00485 likelihood<log_domain, Lvalue, Lvalidator> p(lhs);
00486 p *= rhs;
00487 return p;
00488 }
00489
00491 template <typename Ldomain, typename Lvalue, typename Lvalidator,
00492 typename Rdomain, typename Rvalue, typename Rvalidator>
00493 likelihood<log_domain, Lvalue, Lvalidator>
00494 operator / (const likelihood<Ldomain,Lvalue,Lvalidator>& lhs,
00495 const likelihood<Rdomain,Rvalue,Rvalidator>& rhs)
00496 {
00497 likelihood<log_domain, Lvalue, Lvalidator> p(lhs);
00498 p /= rhs;
00499 return p;
00500 }
00502
00504
00505
00516 #define COMPARE(OP) \
00517 template <typename Ldomain, typename Lvalue, typename Lvalidator, \
00518 typename Rdomain, typename Rvalue, typename Rvalidator> \
00519 bool \
00520 operator OP (const likelihood<Ldomain,Lvalue,Lvalidator>& lhs, \
00521 const likelihood<Rdomain,Rvalue,Rvalidator>& rhs) \
00522 { return lhs.value_cast(log_domain()) OP rhs.value_cast(log_domain()); } \
00523 template <typename Ldomain, typename Lvalue, typename Lvalidator, \
00524 typename Rdomain, typename Rvalue, typename Rvalidator> \
00525 bool \
00526 operator OP (const likelihood<Ldomain,Lvalue,Lvalidator>& lhs, \
00527 const probability<Rdomain,Rvalue,Rvalidator>& rhs) \
00528 { return lhs.value_cast(log_domain()) OP rhs.value_cast(log_domain()); } \
00529 template <typename Ldomain, typename Lvalue, typename Lvalidator, \
00530 typename Rdomain, typename Rvalue, typename Rvalidator> \
00531 bool \
00532 operator OP (const probability<Ldomain,Lvalue,Lvalidator>& lhs, \
00533 const likelihood<Rdomain,Rvalue,Rvalidator>& rhs) \
00534 { return lhs.value_cast(log_domain()) OP rhs.value_cast(log_domain()); }
00535
00536 COMPARE(==)
00537 COMPARE(!=)
00538 COMPARE(<)
00539 COMPARE(<=)
00540 COMPARE(>=)
00541 COMPARE(>)
00542
00543 #undef COMPARE
00544
00556 #define COMPARE_T(OP) \
00557 template <typename Domain,typename Value,typename Validator,typename T> \
00558 bool \
00559 operator OP (const likelihood<Domain,Value,Validator>& lhs, const T& rhs) \
00560 { \
00561 function_requires< ConvertibleConcept<T,Value> >(); \
00562 return lhs.value_cast(linear_domain()) OP rhs; \
00563 } \
00564 template <typename Domain,typename Value,typename Validator,typename T> \
00565 bool \
00566 operator OP (const T& lhs, const likelihood<Domain,Value,Validator>& rhs) \
00567 { \
00568 function_requires< ConvertibleConcept<T,Value> >(); \
00569 return lhs OP rhs.value_cast(linear_domain()); \
00570 }
00571
00572 COMPARE_T(==)
00573 COMPARE_T(!=)
00574 COMPARE_T(<)
00575 COMPARE_T(<=)
00576 COMPARE_T(>=)
00577 COMPARE_T(>)
00578
00579 #undef COMPARE_T
00581
00583
00584
00592 template <typename Domain, typename Value, typename Validator,
00593 typename Integer>
00594 likelihood<Domain, Value, Validator>
00595 pow (const likelihood<Domain,Value,Validator>& base, Integer n)
00596 {
00597 function_requires< boost::IntegerConcept<Integer> >();
00598 return likelihood<Domain,Value,Validator>
00599 (domain_traits<likelihood_tag,Domain,Value>::
00600 pow(base.value_cast(Domain()), n));
00601 }
00603
00604 }
00605
00606 }
00607
00608 namespace std
00609 {
00610
00645 template <typename Domain, typename Value>
00646 struct numeric_limits< boost::probabilities::likelihood<Domain,Value> >
00647 {
00648 static const bool is_specialized = true;
00649
00650 static Value min() throw() { return numeric_limits<Value>::min(); }
00651 static Value max() throw() { return numeric_limits<Value>::max(); }
00652
00653 static const int digits = numeric_limits<Value>::digits;
00654 static const int digits10 = numeric_limits<Value>::digits10;
00655 static const bool is_signed = false;
00656 static const bool is_integer = numeric_limits<Value>::is_integer;
00657 static const bool is_exact = numeric_limits<Value>::is_exact;
00658 static const int radix = numeric_limits<Value>::radix;
00659 static Value epsilon() throw() { return numeric_limits<Value>::epsilon(); }
00660 static Value round_error() throw()
00661 { return numeric_limits<Value>::round_error(); }
00662
00663 static const int min_exponent = numeric_limits<Value>::min_exponent;
00664 static const int min_exponent10 = numeric_limits<Value>::min_exponent10;
00665 static const int max_exponent = numeric_limits<Value>::max_exponent;
00666 static const int max_exponent10 = numeric_limits<Value>::max_exponent10;
00667
00668 static const bool has_infinity = numeric_limits<Value>::has_infinity;
00669 static const bool has_quiet_NaN = numeric_limits<Value>::has_quiet_NaN;
00670 static const bool has_signaling_NaN
00671 = numeric_limits<Value>::has_signaling_NaN;
00672 static const float_denorm_style has_denorm
00673 = numeric_limits<Value>::has_denorm;
00674 static const bool has_denorm_loss = numeric_limits<Value>::has_denorm_loss;
00675
00676 static Value infinity() throw()
00677 { return numeric_limits<Value>::infinity(); }
00678 static Value quiet_NaN() throw()
00679 { return numeric_limits<Value>::quiet_NaN(); }
00680 static Value signaling_NaN() throw()
00681 { return numeric_limits<Value>::signaling_NaN(); }
00682 static Value denorm_min() throw()
00683 { return numeric_limits<Value>::denorm_min(); }
00684
00685 static const bool is_iec559 = numeric_limits<Value>::is_iec559;
00686 static const bool is_bounded = numeric_limits<Value>::is_bounded;
00687 static const bool is_modulo = numeric_limits<Value>::is_modulo;
00688
00689 static const bool traps = numeric_limits<Value>::traps;
00690 static const bool tinyness_before = numeric_limits<Value>::tinyness_before;
00691 static const float_round_style round_style
00692 = numeric_limits<Value>::round_style;
00693 };
00694
00695 }
00696
00697 #endif