logistic.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. // Copyright 2008 Gautam Sewani
  2. // Copyright 2024 Matt Borland
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt
  6. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_MATH_DISTRIBUTIONS_LOGISTIC
  8. #define BOOST_MATH_DISTRIBUTIONS_LOGISTIC
  9. #include <boost/math/tools/config.hpp>
  10. #include <boost/math/tools/numeric_limits.hpp>
  11. #include <boost/math/tools/tuple.hpp>
  12. #include <boost/math/tools/precision.hpp>
  13. #include <boost/math/distributions/fwd.hpp>
  14. #include <boost/math/distributions/detail/common_error_handling.hpp>
  15. #include <boost/math/distributions/complement.hpp>
  16. #include <boost/math/special_functions/log1p.hpp>
  17. #include <boost/math/constants/constants.hpp>
  18. #include <boost/math/policies/policy.hpp>
  19. #include <boost/math/policies/error_handling.hpp>
  20. #include <boost/math/special_functions/logit.hpp>
  21. #include <boost/math/special_functions/logistic_sigmoid.hpp>
  22. namespace boost { namespace math {
  23. template <class RealType = double, class Policy = policies::policy<> >
  24. class logistic_distribution
  25. {
  26. public:
  27. typedef RealType value_type;
  28. typedef Policy policy_type;
  29. BOOST_MATH_GPU_ENABLED logistic_distribution(RealType l_location=0, RealType l_scale=1) // Constructor.
  30. : m_location(l_location), m_scale(l_scale)
  31. {
  32. constexpr auto function = "boost::math::logistic_distribution<%1%>::logistic_distribution";
  33. RealType result;
  34. detail::check_scale(function, l_scale, &result, Policy());
  35. detail::check_location(function, l_location, &result, Policy());
  36. }
  37. // Accessor functions.
  38. BOOST_MATH_GPU_ENABLED RealType scale()const
  39. {
  40. return m_scale;
  41. }
  42. BOOST_MATH_GPU_ENABLED RealType location()const
  43. {
  44. return m_location;
  45. }
  46. private:
  47. // Data members:
  48. RealType m_location; // distribution location aka mu.
  49. RealType m_scale; // distribution scale aka s.
  50. }; // class logistic_distribution
  51. typedef logistic_distribution<double> logistic;
  52. #ifdef __cpp_deduction_guides
  53. template <class RealType>
  54. logistic_distribution(RealType)->logistic_distribution<typename boost::math::tools::promote_args<RealType>::type>;
  55. template <class RealType>
  56. logistic_distribution(RealType,RealType)->logistic_distribution<typename boost::math::tools::promote_args<RealType>::type>;
  57. #endif
  58. template <class RealType, class Policy>
  59. BOOST_MATH_GPU_ENABLED inline const boost::math::pair<RealType, RealType> range(const logistic_distribution<RealType, Policy>& /* dist */)
  60. { // Range of permissible values for random variable x.
  61. using boost::math::tools::max_value;
  62. return boost::math::pair<RealType, RealType>(
  63. boost::math::numeric_limits<RealType>::has_infinity ? -boost::math::numeric_limits<RealType>::infinity() : -max_value<RealType>(),
  64. boost::math::numeric_limits<RealType>::has_infinity ? boost::math::numeric_limits<RealType>::infinity() : max_value<RealType>());
  65. }
  66. template <class RealType, class Policy>
  67. BOOST_MATH_GPU_ENABLED inline const boost::math::pair<RealType, RealType> support(const logistic_distribution<RealType, Policy>& /* dist */)
  68. { // Range of supported values for random variable x.
  69. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
  70. using boost::math::tools::max_value;
  71. return boost::math::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + infinity
  72. }
  73. template <class RealType, class Policy>
  74. BOOST_MATH_GPU_ENABLED inline RealType pdf(const logistic_distribution<RealType, Policy>& dist, const RealType& x)
  75. {
  76. constexpr auto function = "boost::math::pdf(const logistic_distribution<%1%>&, %1%)";
  77. RealType scale = dist.scale();
  78. RealType location = dist.location();
  79. RealType result = 0;
  80. if(false == detail::check_scale(function, scale , &result, Policy()))
  81. {
  82. return result;
  83. }
  84. if(false == detail::check_location(function, location, &result, Policy()))
  85. {
  86. return result;
  87. }
  88. if((boost::math::isinf)(x))
  89. {
  90. return 0; // pdf + and - infinity is zero.
  91. }
  92. if(false == detail::check_x(function, x, &result, Policy()))
  93. {
  94. return result;
  95. }
  96. BOOST_MATH_STD_USING
  97. RealType exp_term = (location - x) / scale;
  98. if(fabs(exp_term) > tools::log_max_value<RealType>())
  99. return 0;
  100. exp_term = exp(exp_term);
  101. if((exp_term * scale > 1) && (exp_term > tools::max_value<RealType>() / (scale * exp_term)))
  102. return 1 / (scale * exp_term);
  103. return (exp_term) / (scale * (1 + exp_term) * (1 + exp_term));
  104. }
  105. template <class RealType, class Policy>
  106. BOOST_MATH_GPU_ENABLED inline RealType cdf(const logistic_distribution<RealType, Policy>& dist, const RealType& x)
  107. {
  108. RealType scale = dist.scale();
  109. RealType location = dist.location();
  110. RealType result = 0; // of checks.
  111. constexpr auto function = "boost::math::cdf(const logistic_distribution<%1%>&, %1%)";
  112. if(false == detail::check_scale(function, scale, &result, Policy()))
  113. {
  114. return result;
  115. }
  116. if(false == detail::check_location(function, location, &result, Policy()))
  117. {
  118. return result;
  119. }
  120. if((boost::math::isinf)(x))
  121. {
  122. if(x < 0) return 0; // -infinity
  123. return 1; // + infinity
  124. }
  125. if(false == detail::check_x(function, x, &result, Policy()))
  126. {
  127. return result;
  128. }
  129. using promoted_real_type = typename policies::evaluation<RealType, Policy>::type;
  130. promoted_real_type power = (static_cast<promoted_real_type>(x) - static_cast<promoted_real_type>(location)) / static_cast<promoted_real_type>(scale);
  131. return logistic_sigmoid(power, policies::make_forwarding_policy_t<Policy>());
  132. }
  133. template <class RealType, class Policy>
  134. BOOST_MATH_GPU_ENABLED inline RealType logcdf(const logistic_distribution<RealType, Policy>& dist, const RealType& x)
  135. {
  136. RealType scale = dist.scale();
  137. RealType location = dist.location();
  138. RealType result = 0; // of checks.
  139. constexpr auto function = "boost::math::logcdf(const logistic_distribution<%1%>&, %1%)";
  140. if(false == detail::check_scale(function, scale, &result, Policy()))
  141. {
  142. return result;
  143. }
  144. if(false == detail::check_location(function, location, &result, Policy()))
  145. {
  146. return result;
  147. }
  148. if((boost::math::isinf)(x))
  149. {
  150. if(x < 0)
  151. {
  152. return 0; // -infinity
  153. }
  154. return 1; // + infinity
  155. }
  156. if(false == detail::check_x(function, x, &result, Policy()))
  157. {
  158. return result;
  159. }
  160. BOOST_MATH_STD_USING
  161. RealType power = (location - x) / scale;
  162. if(power > tools::log_max_value<RealType>())
  163. {
  164. return 0;
  165. }
  166. if(power < -tools::log_max_value<RealType>())
  167. {
  168. return 1;
  169. }
  170. return -log1p(exp(power));
  171. }
  172. template <class RealType, class Policy>
  173. BOOST_MATH_GPU_ENABLED inline RealType quantile(const logistic_distribution<RealType, Policy>& dist, const RealType& p)
  174. {
  175. RealType location = dist.location();
  176. RealType scale = dist.scale();
  177. constexpr auto function = "boost::math::quantile(const logistic_distribution<%1%>&, %1%)";
  178. RealType result = 0;
  179. if(false == detail::check_scale(function, scale, &result, Policy()))
  180. return result;
  181. if(false == detail::check_location(function, location, &result, Policy()))
  182. return result;
  183. if(false == detail::check_probability(function, p, &result, Policy()))
  184. return result;
  185. if(p == 0)
  186. {
  187. return -policies::raise_overflow_error<RealType>(function,"probability argument is 0, must be >0 and <1",Policy());
  188. }
  189. if(p == 1)
  190. {
  191. return policies::raise_overflow_error<RealType>(function,"probability argument is 1, must be >0 and <1",Policy());
  192. }
  193. return location + scale * logit(p, Policy());
  194. } // RealType quantile(const logistic_distribution<RealType, Policy>& dist, const RealType& p)
  195. template <class RealType, class Policy>
  196. BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type<logistic_distribution<RealType, Policy>, RealType>& c)
  197. {
  198. RealType location = c.dist.location();
  199. RealType scale = c.dist.scale();
  200. RealType x = c.param;
  201. constexpr auto function = "boost::math::cdf(const complement(logistic_distribution<%1%>&), %1%)";
  202. RealType result = 0;
  203. if(false == detail::check_scale(function, scale, &result, Policy()))
  204. {
  205. return result;
  206. }
  207. if(false == detail::check_location(function, location, &result, Policy()))
  208. {
  209. return result;
  210. }
  211. if((boost::math::isinf)(x))
  212. {
  213. if(x < 0) return 1; // cdf complement -infinity is unity.
  214. return 0; // cdf complement +infinity is zero.
  215. }
  216. if(false == detail::check_x(function, x, &result, Policy()))
  217. {
  218. return result;
  219. }
  220. using promoted_real_type = typename policies::evaluation<RealType, Policy>::type;
  221. promoted_real_type power = (static_cast<promoted_real_type>(location) - static_cast<promoted_real_type>(x)) / static_cast<promoted_real_type>(scale);
  222. return logistic_sigmoid(power, policies::make_forwarding_policy_t<Policy>());
  223. }
  224. template <class RealType, class Policy>
  225. BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type<logistic_distribution<RealType, Policy>, RealType>& c)
  226. {
  227. BOOST_MATH_STD_USING
  228. RealType location = c.dist.location();
  229. RealType scale = c.dist.scale();
  230. RealType x = c.param;
  231. constexpr auto function = "boost::math::logcdf(const complement(logistic_distribution<%1%>&), %1%)";
  232. RealType result = 0;
  233. if(false == detail::check_scale(function, scale, &result, Policy()))
  234. {
  235. return result;
  236. }
  237. if(false == detail::check_location(function, location, &result, Policy()))
  238. {
  239. return result;
  240. }
  241. if((boost::math::isinf)(x))
  242. {
  243. if(x < 0) return 1; // cdf complement -infinity is unity.
  244. return 0; // cdf complement +infinity is zero.
  245. }
  246. if(false == detail::check_x(function, x, &result, Policy()))
  247. {
  248. return result;
  249. }
  250. RealType power = (x - location) / scale;
  251. if(power > tools::log_max_value<RealType>())
  252. return 0;
  253. if(power < -tools::log_max_value<RealType>())
  254. return 1;
  255. return -log1p(exp(power));
  256. }
  257. template <class RealType, class Policy>
  258. BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type<logistic_distribution<RealType, Policy>, RealType>& c)
  259. {
  260. RealType scale = c.dist.scale();
  261. RealType location = c.dist.location();
  262. constexpr auto function = "boost::math::quantile(const complement(logistic_distribution<%1%>&), %1%)";
  263. RealType result = 0;
  264. if(false == detail::check_scale(function, scale, &result, Policy()))
  265. return result;
  266. if(false == detail::check_location(function, location, &result, Policy()))
  267. return result;
  268. RealType q = c.param;
  269. if(false == detail::check_probability(function, q, &result, Policy()))
  270. return result;
  271. using boost::math::tools::max_value;
  272. if(q == 1)
  273. {
  274. return -policies::raise_overflow_error<RealType>(function,"probability argument is 1, but must be >0 and <1",Policy());
  275. }
  276. if(q == 0)
  277. {
  278. return policies::raise_overflow_error<RealType>(function,"probability argument is 0, but must be >0 and <1",Policy());
  279. }
  280. return location - scale * logit(q, Policy());
  281. }
  282. template <class RealType, class Policy>
  283. BOOST_MATH_GPU_ENABLED inline RealType mean(const logistic_distribution<RealType, Policy>& dist)
  284. {
  285. return dist.location();
  286. } // RealType mean(const logistic_distribution<RealType, Policy>& dist)
  287. template <class RealType, class Policy>
  288. BOOST_MATH_GPU_ENABLED inline RealType variance(const logistic_distribution<RealType, Policy>& dist)
  289. {
  290. BOOST_MATH_STD_USING
  291. RealType scale = dist.scale();
  292. return boost::math::constants::pi<RealType>()*boost::math::constants::pi<RealType>()*scale*scale/3;
  293. } // RealType variance(const logistic_distribution<RealType, Policy>& dist)
  294. template <class RealType, class Policy>
  295. BOOST_MATH_GPU_ENABLED inline RealType mode(const logistic_distribution<RealType, Policy>& dist)
  296. {
  297. return dist.location();
  298. }
  299. template <class RealType, class Policy>
  300. BOOST_MATH_GPU_ENABLED inline RealType median(const logistic_distribution<RealType, Policy>& dist)
  301. {
  302. return dist.location();
  303. }
  304. template <class RealType, class Policy>
  305. BOOST_MATH_GPU_ENABLED inline RealType skewness(const logistic_distribution<RealType, Policy>& /*dist*/)
  306. {
  307. return 0;
  308. } // RealType skewness(const logistic_distribution<RealType, Policy>& dist)
  309. template <class RealType, class Policy>
  310. BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const logistic_distribution<RealType, Policy>& /*dist*/)
  311. {
  312. return static_cast<RealType>(6)/5;
  313. } // RealType kurtosis_excess(const logistic_distribution<RealType, Policy>& dist)
  314. template <class RealType, class Policy>
  315. BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const logistic_distribution<RealType, Policy>& dist)
  316. {
  317. return kurtosis_excess(dist) + 3;
  318. } // RealType kurtosis_excess(const logistic_distribution<RealType, Policy>& dist)
  319. template <class RealType, class Policy>
  320. BOOST_MATH_GPU_ENABLED inline RealType entropy(const logistic_distribution<RealType, Policy>& dist)
  321. {
  322. using std::log;
  323. return 2 + log(dist.scale());
  324. }
  325. }}
  326. // Must come at the end:
  327. #include <boost/math/distributions/detail/derived_accessors.hpp>
  328. #endif // BOOST_MATH_DISTRIBUTIONS_LOGISTIC