rayleigh.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. // Copyright Paul A. Bristow 2007.
  2. // Copyright Matt Borland 2023.
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_STATS_rayleigh_HPP
  7. #define BOOST_STATS_rayleigh_HPP
  8. #include <boost/math/distributions/fwd.hpp>
  9. #include <boost/math/constants/constants.hpp>
  10. #include <boost/math/special_functions/log1p.hpp>
  11. #include <boost/math/special_functions/expm1.hpp>
  12. #include <boost/math/distributions/complement.hpp>
  13. #include <boost/math/distributions/detail/common_error_handling.hpp>
  14. #ifdef _MSC_VER
  15. # pragma warning(push)
  16. # pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
  17. #endif
  18. #include <utility>
  19. #include <limits>
  20. #include <cmath>
  21. namespace boost{ namespace math{
  22. namespace detail
  23. { // Error checks:
  24. template <class RealType, class Policy>
  25. inline bool verify_sigma(const char* function, RealType sigma, RealType* presult, const Policy& pol)
  26. {
  27. if((sigma <= 0) || (!(boost::math::isfinite)(sigma)))
  28. {
  29. *presult = policies::raise_domain_error<RealType>(
  30. function,
  31. "The scale parameter \"sigma\" must be > 0 and finite, but was: %1%.", sigma, pol);
  32. return false;
  33. }
  34. return true;
  35. } // bool verify_sigma
  36. template <class RealType, class Policy>
  37. inline bool verify_rayleigh_x(const char* function, RealType x, RealType* presult, const Policy& pol)
  38. {
  39. if((x < 0) || (boost::math::isnan)(x))
  40. {
  41. *presult = policies::raise_domain_error<RealType>(
  42. function,
  43. "The random variable must be >= 0, but was: %1%.", x, pol);
  44. return false;
  45. }
  46. return true;
  47. } // bool verify_rayleigh_x
  48. } // namespace detail
  49. template <class RealType = double, class Policy = policies::policy<> >
  50. class rayleigh_distribution
  51. {
  52. public:
  53. using value_type = RealType;
  54. using policy_type = Policy;
  55. explicit rayleigh_distribution(RealType l_sigma = 1)
  56. : m_sigma(l_sigma)
  57. {
  58. RealType err;
  59. detail::verify_sigma("boost::math::rayleigh_distribution<%1%>::rayleigh_distribution", l_sigma, &err, Policy());
  60. } // rayleigh_distribution
  61. RealType sigma()const
  62. { // Accessor.
  63. return m_sigma;
  64. }
  65. private:
  66. RealType m_sigma;
  67. }; // class rayleigh_distribution
  68. using rayleigh = rayleigh_distribution<double>;
  69. #ifdef __cpp_deduction_guides
  70. template <class RealType>
  71. rayleigh_distribution(RealType)->rayleigh_distribution<typename boost::math::tools::promote_args<RealType>::type>;
  72. #endif
  73. template <class RealType, class Policy>
  74. inline std::pair<RealType, RealType> range(const rayleigh_distribution<RealType, Policy>& /*dist*/)
  75. { // Range of permissible values for random variable x.
  76. using boost::math::tools::max_value;
  77. return std::pair<RealType, RealType>(static_cast<RealType>(0), std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : max_value<RealType>());
  78. }
  79. template <class RealType, class Policy>
  80. inline std::pair<RealType, RealType> support(const rayleigh_distribution<RealType, Policy>& /*dist*/)
  81. { // Range of supported values for random variable x.
  82. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
  83. using boost::math::tools::max_value;
  84. return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
  85. }
  86. template <class RealType, class Policy>
  87. inline RealType pdf(const rayleigh_distribution<RealType, Policy>& dist, const RealType& x)
  88. {
  89. BOOST_MATH_STD_USING // for ADL of std function exp.
  90. RealType sigma = dist.sigma();
  91. RealType result = 0;
  92. static const char* function = "boost::math::pdf(const rayleigh_distribution<%1%>&, %1%)";
  93. if(false == detail::verify_sigma(function, sigma, &result, Policy()))
  94. {
  95. return result;
  96. }
  97. if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
  98. {
  99. return result;
  100. }
  101. if((boost::math::isinf)(x))
  102. {
  103. return 0;
  104. }
  105. RealType sigmasqr = sigma * sigma;
  106. result = x * (exp(-(x * x) / ( 2 * sigmasqr))) / sigmasqr;
  107. return result;
  108. } // pdf
  109. template <class RealType, class Policy>
  110. inline RealType logpdf(const rayleigh_distribution<RealType, Policy>& dist, const RealType& x)
  111. {
  112. BOOST_MATH_STD_USING // for ADL of std function exp.
  113. const RealType sigma = dist.sigma();
  114. RealType result = -std::numeric_limits<RealType>::infinity();
  115. static const char* function = "boost::math::logpdf(const rayleigh_distribution<%1%>&, %1%)";
  116. if(false == detail::verify_sigma(function, sigma, &result, Policy()))
  117. {
  118. return result;
  119. }
  120. if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
  121. {
  122. return result;
  123. }
  124. if((boost::math::isinf)(x))
  125. {
  126. return result;
  127. }
  128. result = -(x*x)/(2*sigma*sigma) - 2*log(sigma) + log(x);
  129. return result;
  130. } // logpdf
  131. template <class RealType, class Policy>
  132. inline RealType cdf(const rayleigh_distribution<RealType, Policy>& dist, const RealType& x)
  133. {
  134. BOOST_MATH_STD_USING // for ADL of std functions
  135. RealType result = 0;
  136. RealType sigma = dist.sigma();
  137. static const char* function = "boost::math::cdf(const rayleigh_distribution<%1%>&, %1%)";
  138. if(false == detail::verify_sigma(function, sigma, &result, Policy()))
  139. {
  140. return result;
  141. }
  142. if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
  143. {
  144. return result;
  145. }
  146. result = -boost::math::expm1(-x * x / ( 2 * sigma * sigma), Policy());
  147. return result;
  148. } // cdf
  149. template <class RealType, class Policy>
  150. inline RealType logcdf(const rayleigh_distribution<RealType, Policy>& dist, const RealType& x)
  151. {
  152. BOOST_MATH_STD_USING // for ADL of std functions
  153. RealType result = 0;
  154. RealType sigma = dist.sigma();
  155. static const char* function = "boost::math::logcdf(const rayleigh_distribution<%1%>&, %1%)";
  156. if(false == detail::verify_sigma(function, sigma, &result, Policy()))
  157. {
  158. return -std::numeric_limits<RealType>::infinity();
  159. }
  160. if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
  161. {
  162. return -std::numeric_limits<RealType>::infinity();
  163. }
  164. result = log1p(-exp(-x * x / ( 2 * sigma * sigma)), Policy());
  165. return result;
  166. } // logcdf
  167. template <class RealType, class Policy>
  168. inline RealType quantile(const rayleigh_distribution<RealType, Policy>& dist, const RealType& p)
  169. {
  170. BOOST_MATH_STD_USING // for ADL of std functions
  171. RealType result = 0;
  172. RealType sigma = dist.sigma();
  173. static const char* function = "boost::math::quantile(const rayleigh_distribution<%1%>&, %1%)";
  174. if(false == detail::verify_sigma(function, sigma, &result, Policy()))
  175. return result;
  176. if(false == detail::check_probability(function, p, &result, Policy()))
  177. return result;
  178. if(p == 0)
  179. {
  180. return 0;
  181. }
  182. if(p == 1)
  183. {
  184. return policies::raise_overflow_error<RealType>(function, 0, Policy());
  185. }
  186. result = sqrt(-2 * sigma * sigma * boost::math::log1p(-p, Policy()));
  187. return result;
  188. } // quantile
  189. template <class RealType, class Policy>
  190. inline RealType cdf(const complemented2_type<rayleigh_distribution<RealType, Policy>, RealType>& c)
  191. {
  192. BOOST_MATH_STD_USING // for ADL of std functions
  193. RealType result = 0;
  194. RealType sigma = c.dist.sigma();
  195. static const char* function = "boost::math::cdf(const rayleigh_distribution<%1%>&, %1%)";
  196. if(false == detail::verify_sigma(function, sigma, &result, Policy()))
  197. {
  198. return result;
  199. }
  200. RealType x = c.param;
  201. if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
  202. {
  203. return result;
  204. }
  205. RealType ea = x * x / (2 * sigma * sigma);
  206. // Fix for VC11/12 x64 bug in exp(float):
  207. if (ea >= tools::max_value<RealType>())
  208. return 0;
  209. result = exp(-ea);
  210. return result;
  211. } // cdf complement
  212. template <class RealType, class Policy>
  213. inline RealType logcdf(const complemented2_type<rayleigh_distribution<RealType, Policy>, RealType>& c)
  214. {
  215. BOOST_MATH_STD_USING // for ADL of std functions
  216. RealType result = 0;
  217. RealType sigma = c.dist.sigma();
  218. static const char* function = "boost::math::logcdf(const rayleigh_distribution<%1%>&, %1%)";
  219. if(false == detail::verify_sigma(function, sigma, &result, Policy()))
  220. {
  221. return -std::numeric_limits<RealType>::infinity();
  222. }
  223. RealType x = c.param;
  224. if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
  225. {
  226. return -std::numeric_limits<RealType>::infinity();
  227. }
  228. RealType ea = x * x / (2 * sigma * sigma);
  229. // Fix for VC11/12 x64 bug in exp(float):
  230. if (ea >= tools::max_value<RealType>())
  231. return 0;
  232. result = -ea;
  233. return result;
  234. } // logcdf complement
  235. template <class RealType, class Policy>
  236. inline RealType quantile(const complemented2_type<rayleigh_distribution<RealType, Policy>, RealType>& c)
  237. {
  238. BOOST_MATH_STD_USING // for ADL of std functions, log & sqrt.
  239. RealType result = 0;
  240. RealType sigma = c.dist.sigma();
  241. static const char* function = "boost::math::quantile(const rayleigh_distribution<%1%>&, %1%)";
  242. if(false == detail::verify_sigma(function, sigma, &result, Policy()))
  243. {
  244. return result;
  245. }
  246. RealType q = c.param;
  247. if(false == detail::check_probability(function, q, &result, Policy()))
  248. {
  249. return result;
  250. }
  251. if(q == 1)
  252. {
  253. return 0;
  254. }
  255. if(q == 0)
  256. {
  257. return policies::raise_overflow_error<RealType>(function, 0, Policy());
  258. }
  259. result = sqrt(-2 * sigma * sigma * log(q));
  260. return result;
  261. } // quantile complement
  262. template <class RealType, class Policy>
  263. inline RealType mean(const rayleigh_distribution<RealType, Policy>& dist)
  264. {
  265. RealType result = 0;
  266. RealType sigma = dist.sigma();
  267. static const char* function = "boost::math::mean(const rayleigh_distribution<%1%>&, %1%)";
  268. if(false == detail::verify_sigma(function, sigma, &result, Policy()))
  269. {
  270. return result;
  271. }
  272. using boost::math::constants::root_half_pi;
  273. return sigma * root_half_pi<RealType>();
  274. } // mean
  275. template <class RealType, class Policy>
  276. inline RealType variance(const rayleigh_distribution<RealType, Policy>& dist)
  277. {
  278. RealType result = 0;
  279. RealType sigma = dist.sigma();
  280. static const char* function = "boost::math::variance(const rayleigh_distribution<%1%>&, %1%)";
  281. if(false == detail::verify_sigma(function, sigma, &result, Policy()))
  282. {
  283. return result;
  284. }
  285. using boost::math::constants::four_minus_pi;
  286. return four_minus_pi<RealType>() * sigma * sigma / 2;
  287. } // variance
  288. template <class RealType, class Policy>
  289. inline RealType mode(const rayleigh_distribution<RealType, Policy>& dist)
  290. {
  291. return dist.sigma();
  292. }
  293. template <class RealType, class Policy>
  294. inline RealType median(const rayleigh_distribution<RealType, Policy>& dist)
  295. {
  296. using boost::math::constants::root_ln_four;
  297. return root_ln_four<RealType>() * dist.sigma();
  298. }
  299. template <class RealType, class Policy>
  300. inline RealType skewness(const rayleigh_distribution<RealType, Policy>& /*dist*/)
  301. {
  302. return static_cast<RealType>(0.63111065781893713819189935154422777984404221106391L);
  303. // Computed using NTL at 150 bit, about 50 decimal digits.
  304. // 2 * sqrt(pi) * (pi-3) / pow(4, 2/3) - pi
  305. }
  306. template <class RealType, class Policy>
  307. inline RealType kurtosis(const rayleigh_distribution<RealType, Policy>& /*dist*/)
  308. {
  309. return static_cast<RealType>(3.2450893006876380628486604106197544154170667057995L);
  310. // Computed using NTL at 150 bit, about 50 decimal digits.
  311. // 3 - (6*pi*pi - 24*pi + 16) / pow(4-pi, 2)
  312. }
  313. template <class RealType, class Policy>
  314. inline RealType kurtosis_excess(const rayleigh_distribution<RealType, Policy>& /*dist*/)
  315. {
  316. return static_cast<RealType>(0.2450893006876380628486604106197544154170667057995L);
  317. // Computed using NTL at 150 bit, about 50 decimal digits.
  318. // -(6*pi*pi - 24*pi + 16) / pow(4-pi,2)
  319. } // kurtosis_excess
  320. template <class RealType, class Policy>
  321. inline RealType entropy(const rayleigh_distribution<RealType, Policy>& dist)
  322. {
  323. using std::log;
  324. return 1 + log(dist.sigma()*constants::one_div_root_two<RealType>()) + constants::euler<RealType>()/2;
  325. }
  326. } // namespace math
  327. } // namespace boost
  328. #ifdef _MSC_VER
  329. # pragma warning(pop)
  330. #endif
  331. // This include must be at the end, *after* the accessors
  332. // for this distribution have been defined, in order to
  333. // keep compilers that support two-phase lookup happy.
  334. #include <boost/math/distributions/detail/derived_accessors.hpp>
  335. #endif // BOOST_STATS_rayleigh_HPP