z_test.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // (C) Copyright Matt Borland 2021.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_MATH_STATISTICS_Z_TEST_HPP
  6. #define BOOST_MATH_STATISTICS_Z_TEST_HPP
  7. #include <boost/math/distributions/normal.hpp>
  8. #include <boost/math/statistics/univariate_statistics.hpp>
  9. #include <iterator>
  10. #include <type_traits>
  11. #include <utility>
  12. #include <cmath>
  13. namespace boost { namespace math { namespace statistics { namespace detail {
  14. template<typename ReturnType, typename T>
  15. ReturnType one_sample_z_test_impl(T sample_mean, T sample_variance, T sample_size, T assumed_mean)
  16. {
  17. using Real = typename std::tuple_element<0, ReturnType>::type;
  18. using std::sqrt;
  19. using no_promote_policy = boost::math::policies::policy<boost::math::policies::promote_float<false>, boost::math::policies::promote_double<false>>;
  20. Real test_statistic = (sample_mean - assumed_mean) / (sample_variance / sqrt(sample_size));
  21. auto z = boost::math::normal_distribution<Real, no_promote_policy>(sample_size - 1);
  22. Real pvalue;
  23. if(test_statistic > 0)
  24. {
  25. pvalue = 2*boost::math::cdf<Real>(z, -test_statistic);
  26. }
  27. else
  28. {
  29. pvalue = 2*boost::math::cdf<Real>(z, test_statistic);
  30. }
  31. return std::make_pair(test_statistic, pvalue);
  32. }
  33. template<typename ReturnType, typename ForwardIterator>
  34. ReturnType one_sample_z_test_impl(ForwardIterator begin, ForwardIterator end, typename std::iterator_traits<ForwardIterator>::value_type assumed_mean)
  35. {
  36. using Real = typename std::tuple_element<0, ReturnType>::type;
  37. std::pair<Real, Real> temp = mean_and_sample_variance(begin, end);
  38. Real mu = std::get<0>(temp);
  39. Real s_sq = std::get<1>(temp);
  40. return one_sample_z_test_impl<ReturnType>(mu, s_sq, Real(std::distance(begin, end)), Real(assumed_mean));
  41. }
  42. template<typename ReturnType, typename T>
  43. ReturnType two_sample_z_test_impl(T mean_1, T variance_1, T size_1, T mean_2, T variance_2, T size_2)
  44. {
  45. using Real = typename std::tuple_element<0, ReturnType>::type;
  46. using std::sqrt;
  47. using no_promote_policy = boost::math::policies::policy<boost::math::policies::promote_float<false>, boost::math::policies::promote_double<false>>;
  48. Real test_statistic = (mean_1 - mean_2) / sqrt(variance_1/size_1 + variance_2/size_2);
  49. auto z = boost::math::normal_distribution<Real, no_promote_policy>(size_1 + size_2 - 1);
  50. Real pvalue;
  51. if(test_statistic > 0)
  52. {
  53. pvalue = 2*boost::math::cdf<Real>(z, -test_statistic);
  54. }
  55. else
  56. {
  57. pvalue = 2*boost::math::cdf<Real>(z, test_statistic);
  58. }
  59. return std::make_pair(test_statistic, pvalue);
  60. }
  61. template<typename ReturnType, typename ForwardIterator>
  62. ReturnType two_sample_z_test_impl(ForwardIterator begin_1, ForwardIterator end_1, ForwardIterator begin_2, ForwardIterator end_2)
  63. {
  64. using Real = typename std::tuple_element<0, ReturnType>::type;
  65. using std::sqrt;
  66. auto n1 = std::distance(begin_1, end_1);
  67. auto n2 = std::distance(begin_2, end_2);
  68. ReturnType temp_1 = mean_and_sample_variance(begin_1, end_1);
  69. Real mean_1 = std::get<0>(temp_1);
  70. Real variance_1 = std::get<1>(temp_1);
  71. ReturnType temp_2 = mean_and_sample_variance(begin_2, end_2);
  72. Real mean_2 = std::get<0>(temp_2);
  73. Real variance_2 = std::get<1>(temp_2);
  74. return two_sample_z_test_impl<ReturnType>(mean_1, variance_1, Real(n1), mean_2, variance_2, Real(n2));
  75. }
  76. } // detail
  77. template<typename Real, typename std::enable_if<std::is_integral<Real>::value, bool>::type = true>
  78. inline auto one_sample_z_test(Real sample_mean, Real sample_variance, Real sample_size, Real assumed_mean) -> std::pair<double, double>
  79. {
  80. return detail::one_sample_z_test_impl<std::pair<double, double>>(sample_mean, sample_variance, sample_size, assumed_mean);
  81. }
  82. template<typename Real, typename std::enable_if<!std::is_integral<Real>::value, bool>::type = true>
  83. inline auto one_sample_z_test(Real sample_mean, Real sample_variance, Real sample_size, Real assumed_mean) -> std::pair<Real, Real>
  84. {
  85. return detail::one_sample_z_test_impl<std::pair<Real, Real>>(sample_mean, sample_variance, sample_size, assumed_mean);
  86. }
  87. template<typename ForwardIterator, typename Real = typename std::iterator_traits<ForwardIterator>::value_type,
  88. typename std::enable_if<std::is_integral<Real>::value, bool>::type = true>
  89. inline auto one_sample_z_test(ForwardIterator begin, ForwardIterator end, Real assumed_mean) -> std::pair<double, double>
  90. {
  91. return detail::one_sample_z_test_impl<std::pair<double, double>>(begin, end, assumed_mean);
  92. }
  93. template<typename ForwardIterator, typename Real = typename std::iterator_traits<ForwardIterator>::value_type,
  94. typename std::enable_if<!std::is_integral<Real>::value, bool>::type = true>
  95. inline auto one_sample_z_test(ForwardIterator begin, ForwardIterator end, Real assumed_mean) -> std::pair<Real, Real>
  96. {
  97. return detail::one_sample_z_test_impl<std::pair<Real, Real>>(begin, end, assumed_mean);
  98. }
  99. template<typename Container, typename Real = typename Container::value_type,
  100. typename std::enable_if<std::is_integral<Real>::value, bool>::type = true>
  101. inline auto one_sample_z_test(Container const & v, Real assumed_mean) -> std::pair<double, double>
  102. {
  103. return detail::one_sample_z_test_impl<std::pair<double, double>>(std::begin(v), std::end(v), assumed_mean);
  104. }
  105. template<typename Container, typename Real = typename Container::value_type,
  106. typename std::enable_if<!std::is_integral<Real>::value, bool>::type = true>
  107. inline auto one_sample_z_test(Container const & v, Real assumed_mean) -> std::pair<Real, Real>
  108. {
  109. return detail::one_sample_z_test_impl<std::pair<Real, Real>>(std::begin(v), std::end(v), assumed_mean);
  110. }
  111. template<typename ForwardIterator, typename Real = typename std::iterator_traits<ForwardIterator>::value_type,
  112. typename std::enable_if<std::is_integral<Real>::value, bool>::type = true>
  113. inline auto two_sample_z_test(ForwardIterator begin_1, ForwardIterator end_1, ForwardIterator begin_2, ForwardIterator end_2) -> std::pair<double, double>
  114. {
  115. return detail::two_sample_z_test_impl<std::pair<double, double>>(begin_1, end_1, begin_2, end_2);
  116. }
  117. template<typename ForwardIterator, typename Real = typename std::iterator_traits<ForwardIterator>::value_type,
  118. typename std::enable_if<!std::is_integral<Real>::value, bool>::type = true>
  119. inline auto two_sample_z_test(ForwardIterator begin_1, ForwardIterator end_1, ForwardIterator begin_2, ForwardIterator end_2) -> std::pair<Real, Real>
  120. {
  121. return detail::two_sample_z_test_impl<std::pair<Real, Real>>(begin_1, end_1, begin_2, end_2);
  122. }
  123. template<typename Container, typename Real = typename Container::value_type, typename std::enable_if<std::is_integral<Real>::value, bool>::type = true>
  124. inline auto two_sample_z_test(Container const & u, Container const & v) -> std::pair<double, double>
  125. {
  126. return detail::two_sample_z_test_impl<std::pair<double, double>>(std::begin(u), std::end(u), std::begin(v), std::end(v));
  127. }
  128. template<typename Container, typename Real = typename Container::value_type, typename std::enable_if<!std::is_integral<Real>::value, bool>::type = true>
  129. inline auto two_sample_z_test(Container const & u, Container const & v) -> std::pair<Real, Real>
  130. {
  131. return detail::two_sample_z_test_impl<std::pair<Real, Real>>(std::begin(u), std::end(u), std::begin(v), std::end(v));
  132. }
  133. }}} // boost::math::statistics
  134. #endif // BOOST_MATH_STATISTICS_Z_TEST_HPP