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