/* chi_squared_test.hpp header file * * Copyright Steven Watanabe 2010 * Distributed under the Boost Software License, Version 1.0. (See * accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * $Id$ * */ #ifndef BOOST_RANDOM_TEST_CHI_SQUARED_TEST_HPP_INCLUDED #define BOOST_RANDOM_TEST_CHI_SQUARED_TEST_HPP_INCLUDED #include #include #include // This only works for discrete distributions with fixed // upper and lower bounds. template struct chi_squared_collector { static const IntType cutoff = 5; chi_squared_collector() : chi_squared(0), variables(0), prev_actual(0), prev_expected(0), current_actual(0), current_expected(0) {} void operator()(IntType actual, double expected) { current_actual += actual; current_expected += expected; if(current_expected >= cutoff) { if(prev_expected != 0) { update(prev_actual, prev_expected); } prev_actual = current_actual; prev_expected = current_expected; current_actual = 0; current_expected = 0; } } void update(IntType actual, double expected) { chi_squared += boost::math::pow<2>(actual - expected) / expected; ++variables; } double cdf() { if(prev_expected != 0) { update(prev_actual + current_actual, prev_expected + current_expected); prev_actual = 0; prev_expected = 0; current_actual = 0; current_expected = 0; } if(variables <= 1) { return 0; } else { return boost::math::cdf(boost::math::chi_squared(static_cast(variables - 1)), chi_squared); } } double chi_squared; std::size_t variables; IntType prev_actual; double prev_expected; IntType current_actual; double current_expected; }; template double chi_squared_test(const std::vector& results, const std::vector& probabilities, IntType iterations) { chi_squared_collector calc; for(std::size_t i = 0; i < results.size(); ++i) { calc(results[i], iterations * probabilities[i]); } return calc.cdf(); } #endif