// (C) Copyright John Maddock 2006. // Use, modification and distribution are subject to 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) #include #include #include #include #include #include #include #include #include #include #include #include "test_beta_hooks.hpp" template void print_test_result(const boost::math::tools::test_result& result, const Seq& worst, int row, const char* name, const char* test) { using namespace std; // To aid selection of the right pow. T eps = pow(T(2), 1-boost::math::tools::digits()); std::cout << std::setprecision(4); std::cout << test << "(" << name << ") Max = " << (result.stat.max)()/eps << " RMS Mean=" << result.stat.rms()/eps; if((result.stat.max)() != 0) { std::cout << "\n worst case at row: " << row << "\n { "; for(unsigned i = 0; i < worst.size(); ++i) { if(i) std::cout << ", "; std::cout << worst[i]; } std::cout << " }"; } std::cout << std::endl; } template void do_test_beta(const T& data, const char* type_name, const char* test_name) { typedef typename T::value_type row_type; typedef typename row_type::value_type value_type; typedef value_type (*pg)(value_type, value_type, value_type); pg funcp = boost::math::beta; boost::math::tools::test_result result; std::cout << "Testing " << test_name << " with type " << type_name << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"; // // test beta against data: // result = boost::math::tools::test( data, boost::lambda::bind(funcp, boost::lambda::ret(boost::lambda::_1[0]), boost::lambda::ret(boost::lambda::_1[1]), boost::lambda::ret(boost::lambda::_1[2])), boost::lambda::ret(boost::lambda::_1[3])); print_test_result(result, data[result.worst_case], result.worst_case, type_name, "boost::math::beta"); funcp = boost::math::betac; result = boost::math::tools::test( data, boost::lambda::bind(funcp, boost::lambda::ret(boost::lambda::_1[0]), boost::lambda::ret(boost::lambda::_1[1]), boost::lambda::ret(boost::lambda::_1[2])), boost::lambda::ret(boost::lambda::_1[4])); print_test_result(result, data[result.worst_case], result.worst_case, type_name, "boost::math::betac"); funcp = boost::math::ibeta; result = boost::math::tools::test( data, boost::lambda::bind(funcp, boost::lambda::ret(boost::lambda::_1[0]), boost::lambda::ret(boost::lambda::_1[1]), boost::lambda::ret(boost::lambda::_1[2])), boost::lambda::ret(boost::lambda::_1[5])); print_test_result(result, data[result.worst_case], result.worst_case, type_name, "boost::math::ibeta"); funcp = boost::math::ibetac; result = boost::math::tools::test( data, boost::lambda::bind(funcp, boost::lambda::ret(boost::lambda::_1[0]), boost::lambda::ret(boost::lambda::_1[1]), boost::lambda::ret(boost::lambda::_1[2])), boost::lambda::ret(boost::lambda::_1[6])); print_test_result(result, data[result.worst_case], result.worst_case, type_name, "boost::math::ibetac"); #ifdef TEST_OTHER if(::boost::is_floating_point::value){ funcp = other::ibeta; result = boost::math::tools::test( data, boost::lambda::bind(funcp, boost::lambda::ret(boost::lambda::_1[0]), boost::lambda::ret(boost::lambda::_1[1]), boost::lambda::ret(boost::lambda::_1[2])), boost::lambda::ret(boost::lambda::_1[5])); print_test_result(result, data[result.worst_case], result.worst_case, type_name, "other::ibeta"); } #endif std::cout << std::endl; } template void test_inverses(const T& data) { using namespace std; typedef typename T::value_type row_type; typedef typename row_type::value_type value_type; value_type precision = static_cast(ldexp(1.0, 1-boost::math::tools::digits()/2)) * 100; if(boost::math::tools::digits() < 50) precision = 1; // 1% or two decimal digits, all we can hope for when the input is truncated for(unsigned i = 0; i < data.size(); ++i) { // // These inverse tests are thrown off if the output of the // incomplete beta is too close to 1: basically there is insuffient // information left in the value we're using as input to the inverse // to be able to get back to the original value. // if(data[i][5] == 0) BOOST_CHECK_EQUAL(boost::math::ibeta_inv(data[i][0], data[i][1], data[i][5]), value_type(0)); else if((1 - data[i][5] > 0.001) && (fabs(data[i][5]) >= boost::math::tools::min_value())) { value_type inv = boost::math::ibeta_inv(data[i][0], data[i][1], data[i][5]); BOOST_CHECK_CLOSE(data[i][2], inv, precision); } else if(1 == data[i][5]) BOOST_CHECK_EQUAL(boost::math::ibeta_inv(data[i][0], data[i][1], data[i][5]), value_type(1)); if(data[i][6] == 0) BOOST_CHECK_EQUAL(boost::math::ibetac_inv(data[i][0], data[i][1], data[i][6]), value_type(1)); else if((1 - data[i][6] > 0.001) && (fabs(data[i][6]) >= boost::math::tools::min_value())) { value_type inv = boost::math::ibetac_inv(data[i][0], data[i][1], data[i][6]); BOOST_CHECK_CLOSE(data[i][2], inv, precision); } else if(data[i][6] == 1) BOOST_CHECK_EQUAL(boost::math::ibetac_inv(data[i][0], data[i][1], data[i][6]), value_type(0)); } } template void test_beta(T, const char* name) { // // The actual test data is rather verbose, so it's in a separate file // // The contents are as follows, each row of data contains // five items, input value a, input value b, integration limits x, beta(a, b, x) and ibeta(a, b, x): // # include "ibeta_small_data.ipp" do_test_beta(ibeta_small_data, name, "Incomplete Beta Function: Small Values"); test_inverses(ibeta_small_data); # include "ibeta_data.ipp" do_test_beta(ibeta_data, name, "Incomplete Beta Function: Medium Values"); test_inverses(ibeta_data); # include "ibeta_large_data.ipp" do_test_beta(ibeta_large_data, name, "Incomplete Beta Function: Large and Diverse Values"); test_inverses(ibeta_large_data); } template void test_spots(T) { // // basic sanity checks, tolerance is 10 decimal places expressed as a percentage, // One check per domain of the implementation: // T tolerance = std::pow(10.0, -8); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(0.015964560210704803), static_cast(1.1846856068586931e-005), static_cast(0.69176378846168518)), static_cast(0.0007508604820642986204162462167319506309750), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(42.434902191162109), static_cast(0.30012050271034241), static_cast(0.91574394702911377)), static_cast(0.002844243156314242058287766324242276991912), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(9.7131776809692383), static_cast(99.406852722167969), static_cast(0.083912998437881470)), static_cast(0.4612716118626361034813232775095335302198), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(72.695472717285156), static_cast(1.1902070045471191), static_cast(0.80036874115467072)), static_cast(1.703685144285803673344984949797496197040e-7), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(4.9854421615600586), static_cast(1.0665277242660522), static_cast(0.75997146964073181)), static_cast(0.2755954254731642667260071858810487404614), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(6.8127136230468750), static_cast(1.0562920570373535), static_cast(0.17416560649871826)), static_cast(7.702362015088558153029455563361002570531e-6), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(0.48983201384544373), static_cast(0.22512593865394592), static_cast(0.20032680034637451)), static_cast(0.170905142698145967653807992508983970176), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(4.0498137474060059), static_cast(0.15403440594673157), static_cast(0.65370121598243713)), static_cast(0.0172702040689452906446803217247250156007), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(7.2695474624633789), static_cast(0.11902070045471191), static_cast(0.80036874115467072)), static_cast(0.013346136714187857821168127038816508028), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(2.7266697883605957), static_cast(0.011510574258863926), static_cast(0.086654007434844971)), static_cast(5.812020420972734916187451486321162137375e-6), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(0.34317314624786377), static_cast(0.046342257410287857), static_cast(0.75823287665843964)), static_cast(0.151317265120184850887504097401768195067), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(0.34317314624786377), static_cast(0.046342257410287857), static_cast(0)), static_cast(0), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibetac( static_cast(0.34317314624786377), static_cast(0.046342257410287857), static_cast(0)), static_cast(1), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(0.34317314624786377), static_cast(0.046342257410287857), static_cast(1)), static_cast(1), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibetac( static_cast(0.34317314624786377), static_cast(0.046342257410287857), static_cast(1)), static_cast(0), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(1), static_cast(0.046342257410287857), static_cast(0.32)), static_cast(0.0177137046180187568703202426065033413304), tolerance); BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(0.046342257410287857), static_cast(1), static_cast(0.32)), static_cast(0.948565954109602496577407403168592262389), tolerance); } int test_main(int, char* []) { #ifdef TEST_GSL gsl_set_error_handler_off(); #endif //test_spots(0.0F); test_spots(0.0); test_spots(0.0L); test_spots(boost::math::concepts::real_concept(0.1)); test_beta(0.1F, "float"); test_beta(0.1, "double"); test_beta(0.1L, "long double"); test_beta(boost::math::concepts::real_concept(0.1), "real_concept"); return 0; }