test_ellint_3.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright John Maddock 2015.
  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. #ifdef _MSC_VER
  6. # pragma warning (disable : 4224)
  7. #endif
  8. #include <boost/math/special_functions/ellint_3.hpp>
  9. #include <boost/array.hpp>
  10. #include <boost/lexical_cast.hpp>
  11. #include "../../test/table_type.hpp"
  12. #include "table_helper.hpp"
  13. #include "performance.hpp"
  14. #include <iostream>
  15. typedef double T;
  16. #define SC_(x) static_cast<double>(x)
  17. static const boost::array<boost::array<T, 4>, 65> data1 = { {
  18. { { SC_(1.0), SC_(-1.0), SC_(0.0), SC_(-1.557407724654902230506974807458360173087) } },
  19. { { SC_(0.0), SC_(-4.0), SC_(0.4), SC_(-4.153623371196831087495427530365430979011) } },
  20. { { SC_(0.0), SC_(8.0), SC_(-0.6), SC_(8.935930619078575123490612395578518914416) } },
  21. { { SC_(0.0), SC_(0.5), SC_(0.25), SC_(0.501246705365439492445236118603525029757890291780157969500480) } },
  22. { { SC_(0.0), SC_(0.5), SC_(0.0), SC_(0.5) } },
  23. { { SC_(-2.0), SC_(0.5), SC_(0.0), SC_(0.437501067017546278595664813509803743009132067629603474488486) } },
  24. { { SC_(0.25), SC_(0.5), SC_(0.0), SC_(0.510269830229213412212501938035914557628394166585442994564135) } },
  25. { { SC_(0.75), SC_(0.5), SC_(0.0), SC_(0.533293253875952645421201146925578536430596894471541312806165) } },
  26. { { SC_(0.75), SC_(0.75), SC_(0.0), SC_(0.871827580412760575085768367421866079353646112288567703061975) } },
  27. { { SC_(1.0), SC_(0.25), SC_(0.0), SC_(0.255341921221036266504482236490473678204201638800822621740476) } },
  28. { { SC_(2.0), SC_(0.25), SC_(0.0), SC_(0.261119051639220165094943572468224137699644963125853641716219) } },
  29. { { T(1023) / 1024, SC_(1.5), SC_(0.0), SC_(13.2821612239764190363647953338544569682942329604483733197131) } },
  30. { { SC_(0.5), SC_(-1.0), SC_(0.5), SC_(-1.228014414316220642611298946293865487807) } },
  31. { { SC_(0.5), SC_(1e+10), SC_(0.5), SC_(1.536591003599172091573590441336982730551e+10) } },
  32. { { SC_(-1e+05), SC_(10.0), SC_(0.75), SC_(0.0347926099493147087821620459290460547131012904008557007934290) } },
  33. { { SC_(-1e+10), SC_(10.0), SC_(0.875), SC_(0.000109956202759561502329123384755016959364346382187364656768212) } },
  34. { { SC_(-1e+10), SC_(1e+20), SC_(0.875), SC_(1.00000626665567332602765201107198822183913978895904937646809e15) } },
  35. { { SC_(-1e+10), T(1608) / 1024, SC_(0.875), SC_(0.0000157080616044072676127333183571107873332593142625043567690379) } },
  36. { { 1 - T(1) / 1024, SC_(1e+20), SC_(0.875), SC_(6.43274293944380717581167058274600202023334985100499739678963e21) } },
  37. { { SC_(50.0), SC_(0.125), SC_(0.25), SC_(0.196321043776719739372196642514913879497104766409504746018939) } },
  38. { { SC_(1.125), SC_(1.0), SC_(0.25), SC_(1.77299767784815770192352979665283069318388205110727241629752) } },
  39. { { SC_(1.125), SC_(10.0), SC_(0.25), SC_(0.662467818678976949597336360256848770217429434745967677192487) } },
  40. { { SC_(1.125), SC_(3.0), SC_(0.25), SC_(-0.142697285116693775525461312178015106079842313950476205580178) } },
  41. { { T(257) / 256, SC_(1.5), SC_(0.125), SC_(22.2699300473528164111357290313578126108398839810535700884237) } },
  42. { { T(257) / 256, SC_(21.5), SC_(0.125), SC_(-0.535406081652313940727588125663856894154526187713506526799429) } },
  43. // Bug cases from Rocco Romeo:
  44. { { SC_(-1E-170), boost::math::constants::pi<T>() / 4, SC_(1E-164), SC_(0.785398163397448309615660845819875721049292349843776455243736) } },
  45. { { SC_(-1E-170), boost::math::constants::pi<T>() / 4, SC_(-1E-164), SC_(0.785398163397448309615660845819875721049292349843776455243736) } },
  46. { { -ldexp(T(1.0), -52), boost::math::constants::pi<T>() / 4, SC_(0.9375), SC_(0.866032844934895872810905364370384153285798081574191920571016) } },
  47. { { -ldexp(T(1.0), -52), boost::math::constants::pi<T>() / 4, SC_(-0.9375), SC_(0.866032844934895872810905364370384153285798081574191920571016) } },
  48. { { std::numeric_limits<T>::max_exponent > 600 ? -ldexp(T(1), 604) : T(0), -ldexp(T(1), -816), ldexp(T(1), -510), std::numeric_limits<T>::max_exponent > 600 ? SC_(-2.28835573409367516299079046268930870596307631872422530813192e-246) : SC_(-2.28835573409367516299079046268930870596307631872422530813192e-246) } },
  49. { { std::numeric_limits<T>::max_exponent > 600 ? -ldexp(T(1), 604) : T(0), -ldexp(T(1), -816), -ldexp(T(1), -510), std::numeric_limits<T>::max_exponent > 600 ? SC_(-2.28835573409367516299079046268930870596307631872422530813192e-246) : SC_(-2.28835573409367516299079046268930870596307631872422530813192e-246) } },
  50. { { -ldexp(T(1), -622), -ldexp(T(1), -800), ldexp(T(1), -132), SC_(-1.49969681389563095481764443762806535353996169623910829793733e-241) } },
  51. { { -ldexp(T(1), -622), -ldexp(T(1), -800), -ldexp(T(1), -132), SC_(-1.49969681389563095481764443762806535353996169623910829793733e-241) } },
  52. { { -ldexp(T(1), -562), ldexp(T(1), -140), ldexp(T(1), -256), SC_(7.174648137343063403129495466444370592154941142407760751e-43) } },
  53. { { -ldexp(T(1), -562), -ldexp(T(1), -140), ldexp(T(1), -256), SC_(-7.17464813734306340312949546644437059215494114240776075e-43) } },
  54. { { ldexp(T(1), -688), -ldexp(T(1), -243), ldexp(T(1), -193), SC_(-7.07474928033336903711649944600608732865822749854620171e-74) } },
  55. { { -ldexp(T(1), -688), -ldexp(T(1), -243), ldexp(T(1), -193), SC_(-7.07474928033336903711649944600608732865822749854620171e-74) } },
  56. // Special cases where k = 0:
  57. { { SC_(0.5), SC_(1.0), SC_(0.0), SC_(1.17881507892743738986863357869566288974084658835353613038547) } },
  58. { { SC_(-0.5), SC_(1.0), SC_(0.0), SC_(0.888286691263535380266337576823783210424994266596287990733270) } },
  59. { { SC_(0.5), SC_(-1.0), SC_(0.0), SC_(-1.17881507892743738986863357869566288974084658835353613038547) } },
  60. { { SC_(-0.5), SC_(-1.0), SC_(0.0), SC_(-0.888286691263535380266337576823783210424994266596287990733270) } },
  61. // k == 0 and phi > pi/2:
  62. { { SC_(0.5), SC_(2.0), SC_(0.0), SC_(3.03379730757207227653600089552126882582809860566558143254794) } },
  63. { { SC_(-0.5), SC_(2.0), SC_(0.0), SC_(1.57453655812023739911111328195028658229986230310938753315640) } },
  64. { { SC_(0.5), SC_(-2.0), SC_(0.0), SC_(-3.03379730757207227653600089552126882582809860566558143254794) } },
  65. { { SC_(-0.5), SC_(-2.0), SC_(0.0), SC_(-1.57453655812023739911111328195028658229986230310938753315640) } },
  66. // Special cases where k = 1:
  67. { { SC_(0.5), SC_(1.0), SC_(1.0), SC_(1.4830998734200773326887632776553375078936815318419194718912351) } },
  68. { { SC_(-0.5), SC_(1.0), SC_(1.0), SC_(1.07048347329000030842347009377117215811122412769516781788253) } },
  69. { { SC_(0.5), SC_(-1.0), SC_(1.0), SC_(-1.4830998734200773326887632776553375078936815318419194718912) } },
  70. { { SC_(-0.5), SC_(-1.0), SC_(1.0), SC_(-1.07048347329000030842347009377117215811122412769516781788253) } },
  71. // special cases where v = 1:
  72. { { SC_(1.0), SC_(0.5), SC_(0.5), SC_(0.55225234291197632914658859230278152249148960801635386133501) } },
  73. { { SC_(1.0), SC_(-0.5), SC_(0.5), SC_(-0.55225234291197632914658859230278152249148960801635386133501) } },
  74. { { SC_(1.0), SC_(2.0), SC_(0.5), SC_(-2.87534521505997989921579168327307068134740792740155171368532) } },
  75. { { SC_(1.0), SC_(-2.0), SC_(0.5), SC_(2.87534521505997989921579168327307068134740792740155171368532) } },
  76. { { SC_(1.0), SC_(2.0), ldexp(T(1), -200), SC_(-2.18503986326151899164330610231368254343201774622766316456295) } },
  77. { { SC_(1.0), SC_(-2.0), ldexp(T(1), -200), SC_(2.18503986326151899164330610231368254343201774622766316456295) } },
  78. { { SC_(1.0), ldexp(T(1.0), -150), ldexp(T(1), -200), SC_(7.006492321624085354618647916449580656401309709382578858e-46) } },
  79. { { SC_(1.0), -ldexp(T(1.0), -150), ldexp(T(1), -200), SC_(-7.006492321624085354618647916449580656401309709382578858e-46) } },
  80. // Previously unsupported region with v > 1 and |phi| > PI/2, this is the only region
  81. // with high-ish error rates caused by argument reduction by Pi:
  82. { { SC_(20.0), ldexp(T(1647611), -19), SC_(0.5), SC_(0.000975940902692994840122139131147517258405256880370413541280) } },
  83. { { SC_(20.0), -ldexp(T(1647611), -19), SC_(0.5), SC_(-0.000975940902692994840122139131147517258405256880370413541280) } },
  84. { { T(1.0) + ldexp(T(1), -6), ldexp(T(889085), -19), SC_(0.5), SC_(-27.1647225624906589308619292363045712770651414487085887109197) } },
  85. { { T(1.0) + ldexp(T(1), -6), -ldexp(T(889085), -19), SC_(0.5), SC_(27.1647225624906589308619292363045712770651414487085887109197) } },
  86. // Phi = 0:
  87. { { SC_(1.0), SC_(0.0), SC_(0.5), SC_(0.0) } },
  88. { { SC_(-1.0), SC_(0.0), SC_(0.5), SC_(0.0) } },
  89. { { SC_(100.0), SC_(0.0), SC_(0.5), SC_(0.0) } },
  90. { { SC_(-100.0), SC_(0.0), SC_(0.5), SC_(0.0) } },
  91. } };
  92. int main()
  93. {
  94. #include "ellint_pi3_data.ipp"
  95. #include "ellint_pi3_large_data.ipp"
  96. add_data(data1);
  97. add_data(ellint_pi3_data);
  98. add_data(ellint_pi3_large_data);
  99. unsigned data_total = data.size();
  100. std::cout << "Screening boost data:\n";
  101. screen_data([](const std::vector<double>& v){ return boost::math::ellint_3(v[2], v[0], v[1]); }, [](const std::vector<double>& v){ return v[3]; });
  102. #if defined(TEST_LIBSTDCXX) && !defined(COMPILER_COMPARISON_TABLES)
  103. std::cout << "Screening libstdc++ data:\n";
  104. screen_data([](const std::vector<double>& v){ return std::tr1 ::ellint_3(v[2], -v[0], v[1]); }, [](const std::vector<double>& v){ return v[3]; });
  105. #endif
  106. #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES)
  107. std::cout << "Screening libstdc++ data:\n";
  108. screen_data([](const std::vector<double>& v){ return gsl_sf_ellint_P(v[1], v[2], -v[0], GSL_PREC_DOUBLE); }, [](const std::vector<double>& v){ return v[3]; });
  109. #endif
  110. unsigned data_used = data.size();
  111. std::string function = "ellint_3[br](" + boost::lexical_cast<std::string>(data_used) + "/" + boost::lexical_cast<std::string>(data_total) + " tests selected)";
  112. std::string function_short = "ellint_3";
  113. double time;
  114. time = exec_timed_test([](const std::vector<double>& v){ return boost::math::ellint_3(v[2], v[0], v[1]); });
  115. std::cout << time << std::endl;
  116. #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH) || defined(TEST_LIBSTDCXX))
  117. report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name());
  118. #endif
  119. report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name());
  120. //
  121. // Boost again, but with promotion to long double turned off:
  122. //
  123. #if !defined(COMPILER_COMPARISON_TABLES)
  124. if(sizeof(long double) != sizeof(double))
  125. {
  126. time = exec_timed_test([](const std::vector<double>& v){ return boost::math::ellint_3(v[2], v[0], v[1], boost::math::policies::make_policy(boost::math::policies::promote_double<false>())); });
  127. std::cout << time << std::endl;
  128. #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH) || defined(TEST_LIBSTDCXX))
  129. report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name() + "[br]promote_double<false>");
  130. #endif
  131. report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name() + "[br]promote_double<false>");
  132. }
  133. #endif
  134. #if defined(TEST_LIBSTDCXX) && !defined(COMPILER_COMPARISON_TABLES)
  135. time = exec_timed_test([](const std::vector<double>& v){ return std::tr1::ellint_3(v[2], -v[0], v[1]); });
  136. std::cout << time << std::endl;
  137. report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "tr1/cmath");
  138. #endif
  139. #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES)
  140. time = exec_timed_test([](const std::vector<double>& v){ return gsl_sf_ellint_P(v[1], v[2], -v[0], GSL_PREC_DOUBLE); });
  141. std::cout << time << std::endl;
  142. report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "GSL " GSL_VERSION);
  143. #endif
  144. return 0;
  145. }