test_poisson.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. // test_poisson.cpp
  2. // Copyright Paul A. Bristow 2007.
  3. // Copyright John Maddock 2006.
  4. // Use, modification and distribution are subject to the
  5. // Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt
  7. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. // Basic sanity test for Poisson Cumulative Distribution Function.
  9. #define BOOST_MATH_DISCRETE_QUANTILE_POLICY real
  10. #if !defined(TEST_FLOAT) && !defined(TEST_DOUBLE) && !defined(TEST_LDOUBLE) && !defined(TEST_REAL_CONCEPT)
  11. # define TEST_FLOAT
  12. # define TEST_DOUBLE
  13. # define TEST_LDOUBLE
  14. # define TEST_REAL_CONCEPT
  15. #endif
  16. #ifdef _MSC_VER
  17. # pragma warning(disable: 4127) // conditional expression is constant.
  18. #endif
  19. #define BOOST_TEST_MAIN
  20. #include <boost/test/unit_test.hpp> // Boost.Test
  21. #include <boost/test/tools/floating_point_comparison.hpp>
  22. #include <boost/math/concepts/real_concept.hpp> // for real_concept
  23. #include <boost/math/distributions/poisson.hpp>
  24. using boost::math::poisson_distribution;
  25. #include <boost/math/tools/test.hpp> // for real_concept
  26. #include <boost/math/special_functions/gamma.hpp> // for (incomplete) gamma.
  27. // using boost::math::qamma_Q;
  28. #include "table_type.hpp"
  29. #include "test_out_of_range.hpp"
  30. #include <iostream>
  31. using std::cout;
  32. using std::endl;
  33. using std::setprecision;
  34. using std::showpoint;
  35. using std::ios;
  36. #include <limits>
  37. using std::numeric_limits;
  38. template <class RealType> // Any floating-point type RealType.
  39. void test_spots(RealType)
  40. {
  41. // Basic sanity checks, tolerance is about numeric_limits<RealType>::digits10 decimal places,
  42. // guaranteed for type RealType, eg 6 for float, 15 for double,
  43. // expressed as a percentage (so -2) for BOOST_CHECK_CLOSE,
  44. int decdigits = numeric_limits<RealType>::digits10;
  45. // May eb >15 for 80 and 128-bit FP typtes.
  46. if (decdigits <= 0)
  47. { // decdigits is not defined, for example real concept,
  48. // so assume precision of most test data is double (for example, MathCAD).
  49. decdigits = numeric_limits<double>::digits10; // == 15 for 64-bit
  50. }
  51. if (decdigits > 15 ) // numeric_limits<double>::digits10)
  52. { // 15 is the accuracy of the MathCAD test data.
  53. decdigits = 15; // numeric_limits<double>::digits10;
  54. }
  55. decdigits -= 1; // Perhaps allow some decimal digit(s) margin of numerical error.
  56. RealType tolerance = static_cast<RealType>(std::pow(10., static_cast<double>(2-decdigits))); // 1e-6 (-2 so as %)
  57. tolerance *= 2; // Allow some bit(s) small margin (2 means + or - 1 bit) of numerical error.
  58. // Typically 2e-13% = 2e-15 as fraction for double.
  59. // Sources of spot test values:
  60. // Many be some combinations for which the result is 'exact',
  61. // or at least is good to 40 decimal digits.
  62. // 40 decimal digits includes 128-bit significand User Defined Floating-Point types,
  63. // Best source of accurate values is:
  64. // Mathworld online calculator (40 decimal digits precision, suitable for up to 128-bit significands)
  65. // http://functions.wolfram.com/webMathematica/FunctionEvaluation.jsp?name=GammaRegularized
  66. // GammaRegularized is same as gamma incomplete, gamma or gamma_q(a, x) or Q(a, z).
  67. // http://documents.wolfram.com/calculationcenter/v2/Functions/ListsMatrices/Statistics/PoissonDistribution.html
  68. // MathCAD defines ppois(k, lambda== mean) as k integer, k >=0.
  69. // ppois(0, 5) = 6.73794699908547e-3
  70. // ppois(1, 5) = 0.040427681994513;
  71. // ppois(10, 10) = 5.830397501929850E-001
  72. // ppois(10, 1) = 9.999999899522340E-001
  73. // ppois(5,5) = 0.615960654833065
  74. // qpois returns inverse Poission distribution, that is the smallest (floor) k so that ppois(k, lambda) >= p
  75. // p is real number, real mean lambda > 0
  76. // k is approximately the integer for which probability(X <= k) = p
  77. // when random variable X has the Poisson distribution with parameters lambda.
  78. // Uses discrete bisection.
  79. // qpois(6.73794699908547e-3, 5) = 1
  80. // qpois(0.040427681994513, 5) =
  81. // Test Poisson with spot values from MathCAD 'known good'.
  82. using boost::math::poisson_distribution;
  83. using ::boost::math::poisson;
  84. using ::boost::math::cdf;
  85. using ::boost::math::pdf;
  86. // Check that bad arguments throw.
  87. BOOST_MATH_CHECK_THROW(
  88. cdf(poisson_distribution<RealType>(static_cast<RealType>(0)), // mean zero is bad.
  89. static_cast<RealType>(0)), // even for a good k.
  90. std::domain_error); // Expected error to be thrown.
  91. BOOST_MATH_CHECK_THROW(
  92. cdf(poisson_distribution<RealType>(static_cast<RealType>(-1)), // mean negative is bad.
  93. static_cast<RealType>(0)),
  94. std::domain_error);
  95. BOOST_MATH_CHECK_THROW(
  96. cdf(poisson_distribution<RealType>(static_cast<RealType>(1)), // mean unit OK,
  97. static_cast<RealType>(-1)), // but negative events is bad.
  98. std::domain_error);
  99. BOOST_MATH_CHECK_THROW(
  100. cdf(poisson_distribution<RealType>(static_cast<RealType>(0)), // mean zero is bad.
  101. static_cast<RealType>(99999)), // for any k events.
  102. std::domain_error);
  103. BOOST_MATH_CHECK_THROW(
  104. cdf(poisson_distribution<RealType>(static_cast<RealType>(0)), // mean zero is bad.
  105. static_cast<RealType>(99999)), // for any k events.
  106. std::domain_error);
  107. BOOST_MATH_CHECK_THROW(
  108. quantile(poisson_distribution<RealType>(static_cast<RealType>(0)), // mean zero.
  109. static_cast<RealType>(0.5)), // probability OK.
  110. std::domain_error);
  111. BOOST_MATH_CHECK_THROW(
  112. quantile(poisson_distribution<RealType>(static_cast<RealType>(-1)),
  113. static_cast<RealType>(-1)), // bad probability.
  114. std::domain_error);
  115. BOOST_MATH_CHECK_THROW(
  116. quantile(poisson_distribution<RealType>(static_cast<RealType>(1)),
  117. static_cast<RealType>(-1)), // bad probability.
  118. std::domain_error);
  119. BOOST_MATH_CHECK_THROW(
  120. quantile(poisson_distribution<RealType>(static_cast<RealType>(1)),
  121. static_cast<RealType>(1)), // bad probability.
  122. std::overflow_error);
  123. BOOST_MATH_CHECK_THROW(
  124. quantile(complement(poisson_distribution<RealType>(static_cast<RealType>(1)),
  125. static_cast<RealType>(0))), // bad probability.
  126. std::overflow_error);
  127. BOOST_CHECK_EQUAL(
  128. quantile(poisson_distribution<RealType>(static_cast<RealType>(1)),
  129. static_cast<RealType>(0)), // bad probability.
  130. 0);
  131. BOOST_CHECK_EQUAL(
  132. quantile(complement(poisson_distribution<RealType>(static_cast<RealType>(1)),
  133. static_cast<RealType>(1))), // bad probability.
  134. 0);
  135. // Check some test values.
  136. BOOST_CHECK_CLOSE( // mode
  137. mode(poisson_distribution<RealType>(static_cast<RealType>(4))), // mode = mean = 4.
  138. static_cast<RealType>(4), // mode.
  139. tolerance);
  140. //BOOST_CHECK_CLOSE( // mode
  141. // median(poisson_distribution<RealType>(static_cast<RealType>(4))), // mode = mean = 4.
  142. // static_cast<RealType>(4), // mode.
  143. // tolerance);
  144. poisson_distribution<RealType> dist4(static_cast<RealType>(40));
  145. BOOST_CHECK_CLOSE( // median
  146. median(dist4), // mode = mean = 4. median = 40.328333333333333
  147. quantile(dist4, static_cast<RealType>(0.5)), // 39.332839138842637
  148. tolerance);
  149. // PDF
  150. BOOST_CHECK_CLOSE(
  151. pdf(poisson_distribution<RealType>(static_cast<RealType>(4)), // mean 4.
  152. static_cast<RealType>(0)),
  153. static_cast<RealType>(1.831563888873410E-002), // probability.
  154. tolerance);
  155. BOOST_CHECK_CLOSE(
  156. pdf(poisson_distribution<RealType>(static_cast<RealType>(4)), // mean 4.
  157. static_cast<RealType>(2)),
  158. static_cast<RealType>(1.465251111098740E-001), // probability.
  159. tolerance);
  160. BOOST_CHECK_CLOSE(
  161. pdf(poisson_distribution<RealType>(static_cast<RealType>(20)), // mean big.
  162. static_cast<RealType>(1)), // k small
  163. static_cast<RealType>(4.122307244877130E-008), // probability.
  164. tolerance);
  165. BOOST_CHECK_CLOSE(
  166. pdf(poisson_distribution<RealType>(static_cast<RealType>(4)), // mean 4.
  167. static_cast<RealType>(20)), // K>> mean
  168. static_cast<RealType>(8.277463646553730E-009), // probability.
  169. tolerance);
  170. // CDF
  171. BOOST_CHECK_CLOSE(
  172. cdf(poisson_distribution<RealType>(static_cast<RealType>(1)), // mean unity.
  173. static_cast<RealType>(0)), // zero k events.
  174. static_cast<RealType>(3.678794411714420E-1), // probability.
  175. tolerance);
  176. BOOST_CHECK_CLOSE(
  177. cdf(poisson_distribution<RealType>(static_cast<RealType>(1)), // mean unity.
  178. static_cast<RealType>(1)), // one k event.
  179. static_cast<RealType>(7.357588823428830E-1), // probability.
  180. tolerance);
  181. BOOST_CHECK_CLOSE(
  182. cdf(poisson_distribution<RealType>(static_cast<RealType>(1)), // mean unity.
  183. static_cast<RealType>(2)), // two k events.
  184. static_cast<RealType>(9.196986029286060E-1), // probability.
  185. tolerance);
  186. BOOST_CHECK_CLOSE(
  187. cdf(poisson_distribution<RealType>(static_cast<RealType>(1)), // mean unity.
  188. static_cast<RealType>(10)), // two k events.
  189. static_cast<RealType>(9.999999899522340E-1), // probability.
  190. tolerance);
  191. BOOST_CHECK_CLOSE(
  192. cdf(poisson_distribution<RealType>(static_cast<RealType>(1)), // mean unity.
  193. static_cast<RealType>(15)), // two k events.
  194. static_cast<RealType>(9.999999999999810E-1), // probability.
  195. tolerance);
  196. BOOST_CHECK_CLOSE(
  197. cdf(poisson_distribution<RealType>(static_cast<RealType>(1)), // mean unity.
  198. static_cast<RealType>(16)), // two k events.
  199. static_cast<RealType>(9.999999999999990E-1), // probability.
  200. tolerance);
  201. BOOST_CHECK_CLOSE(
  202. cdf(poisson_distribution<RealType>(static_cast<RealType>(1)), // mean unity.
  203. static_cast<RealType>(17)), // two k events.
  204. static_cast<RealType>(1.), // probability unity for double.
  205. tolerance);
  206. BOOST_CHECK_CLOSE(
  207. cdf(poisson_distribution<RealType>(static_cast<RealType>(1)), // mean unity.
  208. static_cast<RealType>(33)), // k events at limit for float unchecked_factorial table.
  209. static_cast<RealType>(1.), // probability.
  210. tolerance);
  211. BOOST_CHECK_CLOSE(
  212. cdf(poisson_distribution<RealType>(static_cast<RealType>(100)), // mean 100.
  213. static_cast<RealType>(33)), // k events at limit for float unchecked_factorial table.
  214. static_cast<RealType>(6.328271240363390E-15), // probability is tiny.
  215. tolerance * static_cast<RealType>(2e11)); // 6.3495253382825722e-015 MathCAD
  216. // Note that there two tiny probability are much more different.
  217. BOOST_CHECK_CLOSE(
  218. cdf(poisson_distribution<RealType>(static_cast<RealType>(100)), // mean 100.
  219. static_cast<RealType>(34)), // k events at limit for float unchecked_factorial table.
  220. static_cast<RealType>(1.898481372109020E-14), // probability is tiny.
  221. tolerance*static_cast<RealType>(2e11)); // 1.8984813721090199e-014 MathCAD
  222. BOOST_CHECK_CLOSE(
  223. cdf(poisson_distribution<RealType>(static_cast<RealType>(33)), // mean = k
  224. static_cast<RealType>(33)), // k events above limit for float unchecked_factorial table.
  225. static_cast<RealType>(5.461191812386560E-1), // probability.
  226. tolerance);
  227. BOOST_CHECK_CLOSE(
  228. cdf(poisson_distribution<RealType>(static_cast<RealType>(33)), // mean = k-1
  229. static_cast<RealType>(34)), // k events above limit for float unchecked_factorial table.
  230. static_cast<RealType>(6.133535681502950E-1), // probability.
  231. tolerance);
  232. BOOST_CHECK_CLOSE(
  233. cdf(poisson_distribution<RealType>(static_cast<RealType>(1)), // mean unity.
  234. static_cast<RealType>(34)), // k events above limit for float unchecked_factorial table.
  235. static_cast<RealType>(1.), // probability.
  236. tolerance);
  237. BOOST_CHECK_CLOSE(
  238. cdf(poisson_distribution<RealType>(static_cast<RealType>(5.)), // mean
  239. static_cast<RealType>(5)), // k events.
  240. static_cast<RealType>(0.615960654833065), // probability.
  241. tolerance);
  242. BOOST_CHECK_CLOSE(
  243. cdf(poisson_distribution<RealType>(static_cast<RealType>(5.)), // mean
  244. static_cast<RealType>(1)), // k events.
  245. static_cast<RealType>(0.040427681994512805), // probability.
  246. tolerance);
  247. BOOST_CHECK_CLOSE(
  248. cdf(poisson_distribution<RealType>(static_cast<RealType>(5.)), // mean
  249. static_cast<RealType>(0)), // k events (uses special case formula, not gamma).
  250. static_cast<RealType>(0.006737946999085467), // probability.
  251. tolerance);
  252. BOOST_CHECK_CLOSE(
  253. cdf(poisson_distribution<RealType>(static_cast<RealType>(1.)), // mean
  254. static_cast<RealType>(0)), // k events (uses special case formula, not gamma).
  255. static_cast<RealType>(0.36787944117144233), // probability.
  256. tolerance);
  257. BOOST_CHECK_CLOSE(
  258. cdf(poisson_distribution<RealType>(static_cast<RealType>(10.)), // mean
  259. static_cast<RealType>(10)), // k events.
  260. static_cast<RealType>(0.5830397501929856), // probability.
  261. tolerance);
  262. BOOST_CHECK_CLOSE(
  263. cdf(poisson_distribution<RealType>(static_cast<RealType>(4.)), // mean
  264. static_cast<RealType>(5)), // k events.
  265. static_cast<RealType>(0.785130387030406), // probability.
  266. tolerance);
  267. // complement CDF
  268. BOOST_CHECK_CLOSE( // Complement CDF
  269. cdf(complement(poisson_distribution<RealType>(static_cast<RealType>(4.)), // mean
  270. static_cast<RealType>(5))), // k events.
  271. static_cast<RealType>(1 - 0.785130387030406), // probability.
  272. tolerance);
  273. BOOST_CHECK_CLOSE( // Complement CDF
  274. cdf(complement(poisson_distribution<RealType>(static_cast<RealType>(4.)), // mean
  275. static_cast<RealType>(0))), // Zero k events (uses special case formula, not gamma).
  276. static_cast<RealType>(0.98168436111126578), // probability.
  277. tolerance);
  278. BOOST_CHECK_CLOSE( // Complement CDF
  279. cdf(complement(poisson_distribution<RealType>(static_cast<RealType>(1.)), // mean
  280. static_cast<RealType>(0))), // Zero k events (uses special case formula, not gamma).
  281. static_cast<RealType>(0.63212055882855767), // probability.
  282. tolerance);
  283. // Example where k is bigger than max_factorial (>34 for float)
  284. // (therefore using log gamma so perhaps less accurate).
  285. BOOST_CHECK_CLOSE(
  286. cdf(poisson_distribution<RealType>(static_cast<RealType>(40.)), // mean
  287. static_cast<RealType>(40)), // k events.
  288. static_cast<RealType>(0.5419181783625430), // probability.
  289. tolerance);
  290. // Quantile & complement.
  291. BOOST_CHECK_CLOSE(
  292. boost::math::quantile(
  293. poisson_distribution<RealType>(5), // mean.
  294. static_cast<RealType>(0.615960654833065)), // probability.
  295. static_cast<RealType>(5.), // Expect k = 5
  296. tolerance/5); //
  297. // EQUAL is too optimistic - fails [5.0000000000000124 != 5]
  298. // BOOST_CHECK_EQUAL(boost::math::quantile( //
  299. // poisson_distribution<RealType>(5.), // mean.
  300. // static_cast<RealType>(0.615960654833065)), // probability.
  301. // static_cast<RealType>(5.)); // Expect k = 5 events.
  302. BOOST_CHECK_CLOSE(boost::math::quantile(
  303. poisson_distribution<RealType>(4), // mean.
  304. static_cast<RealType>(0.785130387030406)), // probability.
  305. static_cast<RealType>(5.), // Expect k = 5 events.
  306. tolerance/5);
  307. // Check on quantile of other examples of inverse of cdf.
  308. BOOST_CHECK_CLOSE(
  309. cdf(poisson_distribution<RealType>(static_cast<RealType>(10.)), // mean
  310. static_cast<RealType>(10)), // k events.
  311. static_cast<RealType>(0.5830397501929856), // probability.
  312. tolerance);
  313. BOOST_CHECK_CLOSE(boost::math::quantile( // inverse of cdf above.
  314. poisson_distribution<RealType>(10.), // mean.
  315. static_cast<RealType>(0.5830397501929856)), // probability.
  316. static_cast<RealType>(10.), // Expect k = 10 events.
  317. tolerance/5);
  318. BOOST_CHECK_CLOSE(
  319. cdf(poisson_distribution<RealType>(static_cast<RealType>(4.)), // mean
  320. static_cast<RealType>(5)), // k events.
  321. static_cast<RealType>(0.785130387030406), // probability.
  322. tolerance);
  323. BOOST_CHECK_CLOSE(boost::math::quantile( // inverse of cdf above.
  324. poisson_distribution<RealType>(4.), // mean.
  325. static_cast<RealType>(0.785130387030406)), // probability.
  326. static_cast<RealType>(5.), // Expect k = 10 events.
  327. tolerance/5);
  328. //BOOST_CHECK_CLOSE(boost::math::quantile(
  329. // poisson_distribution<RealType>(5), // mean.
  330. // static_cast<RealType>(0.785130387030406)), // probability.
  331. // // 6.1882832344329559 result but MathCAD givest smallest integer ppois(k, mean) >= prob
  332. // static_cast<RealType>(6.), // Expect k = 6 events.
  333. // tolerance/5);
  334. //BOOST_CHECK_CLOSE(boost::math::quantile(
  335. // poisson_distribution<RealType>(5), // mean.
  336. // static_cast<RealType>(0.77)), // probability.
  337. // // 6.1882832344329559 result but MathCAD givest smallest integer ppois(k, mean) >= prob
  338. // static_cast<RealType>(7.), // Expect k = 6 events.
  339. // tolerance/5);
  340. //BOOST_CHECK_CLOSE(boost::math::quantile(
  341. // poisson_distribution<RealType>(5), // mean.
  342. // static_cast<RealType>(0.75)), // probability.
  343. // // 6.1882832344329559 result but MathCAD givest smallest integer ppois(k, mean) >= prob
  344. // static_cast<RealType>(6.), // Expect k = 6 events.
  345. // tolerance/5);
  346. BOOST_CHECK_CLOSE(
  347. boost::math::quantile(
  348. complement(
  349. poisson_distribution<RealType>(4),
  350. static_cast<RealType>(1 - 0.785130387030406))), // complement.
  351. static_cast<RealType>(5), // Expect k = 5 events.
  352. tolerance/5);
  353. BOOST_CHECK_EQUAL(boost::math::quantile( // Check case when probability < cdf(0) (== pdf(0))
  354. poisson_distribution<RealType>(1), // mean is small, so cdf and pdf(0) are about 0.35.
  355. static_cast<RealType>(0.0001)), // probability < cdf(0).
  356. static_cast<RealType>(0)); // Expect k = 0 events exactly.
  357. BOOST_CHECK_EQUAL(
  358. boost::math::quantile(
  359. complement(
  360. poisson_distribution<RealType>(1),
  361. static_cast<RealType>(0.9999))), // complement, so 1-probability < cdf(0)
  362. static_cast<RealType>(0)); // Expect k = 0 events exactly.
  363. //
  364. // Test quantile policies against test data:
  365. //
  366. #define T RealType
  367. #include "poisson_quantile.ipp"
  368. for(unsigned i = 0; i < poisson_quantile_data.size(); ++i)
  369. {
  370. using namespace boost::math::policies;
  371. typedef policy<discrete_quantile<boost::math::policies::real> > P1;
  372. typedef policy<discrete_quantile<integer_round_down> > P2;
  373. typedef policy<discrete_quantile<integer_round_up> > P3;
  374. typedef policy<discrete_quantile<integer_round_outwards> > P4;
  375. typedef policy<discrete_quantile<integer_round_inwards> > P5;
  376. typedef policy<discrete_quantile<integer_round_nearest> > P6;
  377. RealType tol = boost::math::tools::epsilon<RealType>() * 20;
  378. if(!boost::is_floating_point<RealType>::value)
  379. tol *= 7;
  380. //
  381. // Check full real value first:
  382. //
  383. poisson_distribution<RealType, P1> p1(poisson_quantile_data[i][0]);
  384. RealType x = quantile(p1, poisson_quantile_data[i][1]);
  385. BOOST_CHECK_CLOSE_FRACTION(x, poisson_quantile_data[i][2], tol);
  386. x = quantile(complement(p1, poisson_quantile_data[i][1]));
  387. BOOST_CHECK_CLOSE_FRACTION(x, poisson_quantile_data[i][3], tol * 3);
  388. //
  389. // Now with round down to integer:
  390. //
  391. poisson_distribution<RealType, P2> p2(poisson_quantile_data[i][0]);
  392. x = quantile(p2, poisson_quantile_data[i][1]);
  393. BOOST_CHECK_EQUAL(x, floor(poisson_quantile_data[i][2]));
  394. x = quantile(complement(p2, poisson_quantile_data[i][1]));
  395. BOOST_CHECK_EQUAL(x, floor(poisson_quantile_data[i][3]));
  396. //
  397. // Now with round up to integer:
  398. //
  399. poisson_distribution<RealType, P3> p3(poisson_quantile_data[i][0]);
  400. x = quantile(p3, poisson_quantile_data[i][1]);
  401. BOOST_CHECK_EQUAL(x, ceil(poisson_quantile_data[i][2]));
  402. x = quantile(complement(p3, poisson_quantile_data[i][1]));
  403. BOOST_CHECK_EQUAL(x, ceil(poisson_quantile_data[i][3]));
  404. //
  405. // Now with round to integer "outside":
  406. //
  407. poisson_distribution<RealType, P4> p4(poisson_quantile_data[i][0]);
  408. x = quantile(p4, poisson_quantile_data[i][1]);
  409. BOOST_CHECK_EQUAL(x, poisson_quantile_data[i][1] < 0.5f ? floor(poisson_quantile_data[i][2]) : ceil(poisson_quantile_data[i][2]));
  410. x = quantile(complement(p4, poisson_quantile_data[i][1]));
  411. BOOST_CHECK_EQUAL(x, poisson_quantile_data[i][1] < 0.5f ? ceil(poisson_quantile_data[i][3]) : floor(poisson_quantile_data[i][3]));
  412. //
  413. // Now with round to integer "inside":
  414. //
  415. poisson_distribution<RealType, P5> p5(poisson_quantile_data[i][0]);
  416. x = quantile(p5, poisson_quantile_data[i][1]);
  417. BOOST_CHECK_EQUAL(x, poisson_quantile_data[i][1] < 0.5f ? ceil(poisson_quantile_data[i][2]) : floor(poisson_quantile_data[i][2]));
  418. x = quantile(complement(p5, poisson_quantile_data[i][1]));
  419. BOOST_CHECK_EQUAL(x, poisson_quantile_data[i][1] < 0.5f ? floor(poisson_quantile_data[i][3]) : ceil(poisson_quantile_data[i][3]));
  420. //
  421. // Now with round to nearest integer:
  422. //
  423. poisson_distribution<RealType, P6> p6(poisson_quantile_data[i][0]);
  424. x = quantile(p6, poisson_quantile_data[i][1]);
  425. BOOST_CHECK_EQUAL(x, floor(poisson_quantile_data[i][2] + 0.5f));
  426. x = quantile(complement(p6, poisson_quantile_data[i][1]));
  427. BOOST_CHECK_EQUAL(x, floor(poisson_quantile_data[i][3] + 0.5f));
  428. }
  429. check_out_of_range<poisson_distribution<RealType> >(1);
  430. } // template <class RealType>void test_spots(RealType)
  431. //
  432. BOOST_AUTO_TEST_CASE( test_main )
  433. {
  434. // Check that can construct normal distribution using the two convenience methods:
  435. using namespace boost::math;
  436. poisson myp1(2); // Using typedef
  437. poisson_distribution<> myp2(2); // Using default RealType double.
  438. // Basic sanity-check spot values.
  439. // Some plain double examples & tests:
  440. cout.precision(17); // double max_digits10
  441. cout.setf(ios::showpoint);
  442. poisson mypoisson(4.); // // mean = 4, default FP type is double.
  443. cout << "mean(mypoisson, 4.) == " << mean(mypoisson) << endl;
  444. cout << "mean(mypoisson, 0.) == " << mean(mypoisson) << endl;
  445. cout << "cdf(mypoisson, 2.) == " << cdf(mypoisson, 2.) << endl;
  446. cout << "pdf(mypoisson, 2.) == " << pdf(mypoisson, 2.) << endl;
  447. // poisson mydudpoisson(0.);
  448. // throws (if BOOST_MATH_DOMAIN_ERROR_POLICY == throw_on_error).
  449. #ifndef BOOST_NO_EXCEPTIONS
  450. BOOST_MATH_CHECK_THROW(poisson mydudpoisson(-1), std::domain_error);// Mean must be > 0.
  451. BOOST_MATH_CHECK_THROW(poisson mydudpoisson(-1), std::logic_error);// Mean must be > 0.
  452. #else
  453. BOOST_MATH_CHECK_THROW(poisson(-1), std::domain_error);// Mean must be > 0.
  454. BOOST_MATH_CHECK_THROW(poisson(-1), std::logic_error);// Mean must be > 0.
  455. #endif
  456. // Passes the check because logic_error is a parent????
  457. // BOOST_MATH_CHECK_THROW(poisson mydudpoisson(-1), std::overflow_error); // fails the check
  458. // because overflow_error is unrelated - except from std::exception
  459. BOOST_MATH_CHECK_THROW(cdf(mypoisson, -1), std::domain_error); // k must be >= 0
  460. BOOST_CHECK_EQUAL(mean(mypoisson), 4.);
  461. BOOST_CHECK_CLOSE(
  462. pdf(mypoisson, 2.), // k events = 2.
  463. 1.465251111098740E-001, // probability.
  464. 5e-13);
  465. BOOST_CHECK_CLOSE(
  466. cdf(mypoisson, 2.), // k events = 2.
  467. 0.238103305553545, // probability.
  468. 5e-13);
  469. #if 0
  470. // Compare cdf from finite sum of pdf and gamma_q.
  471. using boost::math::cdf;
  472. using boost::math::pdf;
  473. double mean = 4.;
  474. cout.precision(17); // double max_digits10
  475. cout.setf(ios::showpoint);
  476. cout << showpoint << endl; // Ensure trailing zeros are shown.
  477. // This also helps show the expected precision max_digits10
  478. //cout.unsetf(ios::showpoint); // No trailing zeros are shown.
  479. cout << "k pdf sum cdf diff" << endl;
  480. double sum = 0.;
  481. for (int i = 0; i <= 50; i++)
  482. {
  483. cout << i << ' ' ;
  484. double p = pdf(poisson_distribution<double>(mean), static_cast<double>(i));
  485. sum += p;
  486. cout << p << ' ' << sum << ' '
  487. << cdf(poisson_distribution<double>(mean), static_cast<double>(i)) << ' ';
  488. {
  489. cout << boost::math::gamma_q<double>(i+1, mean); // cdf
  490. double diff = boost::math::gamma_q<double>(i+1, mean) - sum; // cdf -sum
  491. cout << setprecision (2) << ' ' << diff; // 0 0 to 4, 1 eps 5 to 9, 10 to 20 2 eps, 21 upwards 3 eps
  492. }
  493. BOOST_CHECK_CLOSE(
  494. cdf(mypoisson, static_cast<double>(i)),
  495. sum, // of pdfs.
  496. 4e-14); // Fails at 2e-14
  497. // This call puts the precision etc back to default 6 !!!
  498. cout << setprecision(17) << showpoint;
  499. cout << endl;
  500. }
  501. cout << cdf(poisson_distribution<double>(5), static_cast<double>(0)) << ' ' << endl; // 0.006737946999085467
  502. cout << cdf(poisson_distribution<double>(5), static_cast<double>(1)) << ' ' << endl; // 0.040427681994512805
  503. cout << cdf(poisson_distribution<double>(2), static_cast<double>(3)) << ' ' << endl; // 0.85712346049854715
  504. { // Compare approximate formula in Wikipedia with quantile(half)
  505. for (int i = 1; i < 100; i++)
  506. {
  507. poisson_distribution<double> distn(static_cast<double>(i));
  508. cout << i << ' ' << median(distn) << ' ' << quantile(distn, 0.5) << ' '
  509. << median(distn) - quantile(distn, 0.5) << endl; // formula appears to be out-by-one??
  510. } // so quantile(half) used via derived accressors.
  511. }
  512. #endif
  513. // (Parameter value, arbitrarily zero, only communicates the floating-point type).
  514. #ifdef TEST_POISSON
  515. test_spots(0.0F); // Test float.
  516. #endif
  517. #ifdef TEST_DOUBLE
  518. test_spots(0.0); // Test double.
  519. #endif
  520. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  521. if (numeric_limits<long double>::digits10 > numeric_limits<double>::digits10)
  522. { // long double is better than double (so not MSVC where they are same).
  523. #ifdef TEST_LDOUBLE
  524. test_spots(0.0L); // Test long double.
  525. #endif
  526. }
  527. #ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS
  528. #ifdef TEST_REAL_CONCEPT
  529. test_spots(boost::math::concepts::real_concept(0.)); // Test real concept.
  530. #endif
  531. #endif
  532. #endif
  533. } // BOOST_AUTO_TEST_CASE( test_main )
  534. /*
  535. Output:
  536. Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\test_poisson.exe"
  537. Running 1 test case...
  538. mean(mypoisson, 4.) == 4.0000000000000000
  539. mean(mypoisson, 0.) == 4.0000000000000000
  540. cdf(mypoisson, 2.) == 0.23810330555354431
  541. pdf(mypoisson, 2.) == 0.14652511110987343
  542. *** No errors detected
  543. */