diff options
Diffstat (limited to 'src/boost/libs/math/tools')
64 files changed, 14820 insertions, 0 deletions
diff --git a/src/boost/libs/math/tools/Jamfile.v2 b/src/boost/libs/math/tools/Jamfile.v2 new file mode 100644 index 00000000..5b8a4e83 --- /dev/null +++ b/src/boost/libs/math/tools/Jamfile.v2 @@ -0,0 +1,47 @@ +# Copyright John Maddock 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. +# \math_toolkit\libs\math\test\jamfile.v2 +# Runs all math toolkit tests, functions & distributions, +# and build math examples. + +# bring in the rules for testing +import modules ; +import path ; + +project + : requirements + <toolset>gcc:<cxxflags>-Wno-missing-braces + <toolset>darwin:<cxxflags>-Wno-missing-braces + <toolset>acc:<cxxflags>+W2068,2461,2236,4070,4069 + <toolset>intel-win:<cxxflags>-nologo + <toolset>intel-win:<linkflags>-nologo + <toolset>msvc:<warnings>all + <toolset>msvc:<asynch-exceptions>on + <toolset>msvc:<cxxflags>/wd4996 + <toolset>msvc:<cxxflags>/wd4512 + <toolset>msvc:<cxxflags>/wd4610 + <toolset>msvc:<cxxflags>/wd4510 + <toolset>msvc:<cxxflags>/wd4127 + <toolset>msvc:<cxxflags>/wd4701 # needed for lexical cast - temporary. + <link>static + <toolset>borland:<runtime-link>static + <include>../../.. + <define>BOOST_ALL_NO_LIB=1 + <define>BOOST_UBLAS_UNSUPPORTED_COMPILER=0 + <include>. + <include>../include_private + ; + + +for local source in [ glob *_data.cpp ] generate_test_values.cpp igamma_temme_large_coef.cpp lanczos_generator.cpp factorial_tables.cpp generate_rational_test.cpp +{ + exe $(source:B) : $(source) ; + install $(source:B)_bin : $(source:B) : <location>bin ; +} + +exe generate_rational_code : generate_rational_code.cpp ; +exe process_perf_results : process_perf_results.cpp ../../regex/build//boost_regex ; + +install bin : generate_rational_code process_perf_results ; diff --git a/src/boost/libs/math/tools/bessel_data.cpp b/src/boost/libs/math/tools/bessel_data.cpp new file mode 100644 index 00000000..6c950358 --- /dev/null +++ b/src/boost/libs/math/tools/bessel_data.cpp @@ -0,0 +1,355 @@ +// Copyright (c) 2007 John Maddock +// 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) +// +// Computes test data for the various bessel functions using +// archived - deliberately naive - version of the code. +// We'll rely on the high precision of mp_t to get us out of +// trouble and not worry about how long the calculations take. +// This provides a reasonably independent set of test data to +// compare against newly added asymptotic expansions etc. +// +#include <fstream> + +#include <boost/math/tools/test_data.hpp> +#include <boost/math/special_functions/bessel.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace boost::math::detail; +using namespace std; + +// Compute J(v, x) and Y(v, x) simultaneously by Steed's method, see +// Barnett et al, Computer Physics Communications, vol 8, 377 (1974) +template <typename T> +int bessel_jy_bare(T v, T x, T* J, T* Y, int kind = need_j|need_y) +{ + // Jv1 = J_(v+1), Yv1 = Y_(v+1), fv = J_(v+1) / J_v + // Ju1 = J_(u+1), Yu1 = Y_(u+1), fu = J_(u+1) / J_u + T u, Jv, Ju, Yv, Yv1, Yu, Yu1, fv, fu; + T W, p, q, gamma, current, prev, next; + bool reflect = false; + int n, k, s; + + using namespace std; + using namespace boost::math::tools; + using namespace boost::math::constants; + + if (v < 0) + { + reflect = true; + v = -v; // v is non-negative from here + kind = need_j|need_y; // need both for reflection formula + } + n = real_cast<int>(v + 0.5L); + u = v - n; // -1/2 <= u < 1/2 + + if (x < 0) + { + *J = *Y = policies::raise_domain_error<T>("", + "Real argument x=%1% must be non-negative, complex number result not supported", x, policies::policy<>()); + return 1; + } + if (x == 0) + { + *J = *Y = policies::raise_overflow_error<T>( + "", 0, policies::policy<>()); + return 1; + } + + // x is positive until reflection + W = T(2) / (x * pi<T>()); // Wronskian + if (x <= 2) // x in (0, 2] + { + if(temme_jy(u, x, &Yu, &Yu1, policies::policy<>())) // Temme series + { + // domain error: + *J = *Y = Yu; + return 1; + } + prev = Yu; + current = Yu1; + for (k = 1; k <= n; k++) // forward recurrence for Y + { + next = 2 * (u + k) * current / x - prev; + prev = current; + current = next; + } + Yv = prev; + Yv1 = current; + CF1_jy(v, x, &fv, &s, policies::policy<>()); // continued fraction CF1 + Jv = W / (Yv * fv - Yv1); // Wronskian relation + } + else // x in (2, \infty) + { + // Get Y(u, x): + CF1_jy(v, x, &fv, &s, policies::policy<>()); + // tiny initial value to prevent overflow + T init = sqrt(tools::min_value<T>()); + prev = fv * s * init; + current = s * init; + for (k = n; k > 0; k--) // backward recurrence for J + { + next = 2 * (u + k) * current / x - prev; + prev = current; + current = next; + } + T ratio = (s * init) / current; // scaling ratio + // can also call CF1() to get fu, not much difference in precision + fu = prev / current; + CF2_jy(u, x, &p, &q, policies::policy<>()); // continued fraction CF2 + T t = u / x - fu; // t = J'/J + gamma = (p - t) / q; + Ju = sign(current) * sqrt(W / (q + gamma * (p - t))); + + Jv = Ju * ratio; // normalization + + Yu = gamma * Ju; + Yu1 = Yu * (u/x - p - q/gamma); + + // compute Y: + prev = Yu; + current = Yu1; + for (k = 1; k <= n; k++) // forward recurrence for Y + { + next = 2 * (u + k) * current / x - prev; + prev = current; + current = next; + } + Yv = prev; + } + + if (reflect) + { + T z = (u + n % 2) * pi<T>(); + *J = cos(z) * Jv - sin(z) * Yv; // reflection formula + *Y = sin(z) * Jv + cos(z) * Yv; + } + else + { + *J = Jv; + *Y = Yv; + } + + return 0; +} + +int progress = 0; + +template <class T> +T cyl_bessel_j_bare(T v, T x) +{ + T j, y; + bessel_jy_bare(v, x, &j, &y); + + std::cout << progress++ << ": J(" << v << ", " << x << ") = " << j << std::endl; + + if(fabs(j) > 1e30) + throw std::domain_error(""); + + return j; +} + +template <class T> +T cyl_bessel_i_bare(T v, T x) +{ + using namespace std; + if(x < 0) + { + // better have integer v: + if(floor(v) == v) + { + T r = cyl_bessel_i_bare(v, -x); + if(tools::real_cast<int>(v) & 1) + r = -r; + return r; + } + else + return policies::raise_domain_error<T>( + "", + "Got x = %1%, but we need x >= 0", x, policies::policy<>()); + } + if(x == 0) + { + return (v == 0) ? 1 : 0; + } + T I, K; + boost::math::detail::bessel_ik(v, x, &I, &K, 0xffff, policies::policy<>()); + + std::cout << progress++ << ": I(" << v << ", " << x << ") = " << I << std::endl; + + if(fabs(I) > 1e30) + throw std::domain_error(""); + + return I; +} + +template <class T> +T cyl_bessel_k_bare(T v, T x) +{ + using namespace std; + if(x < 0) + { + return policies::raise_domain_error<T>( + "", + "Got x = %1%, but we need x > 0", x, policies::policy<>()); + } + if(x == 0) + { + return (v == 0) ? policies::raise_overflow_error<T>("", 0, policies::policy<>()) + : policies::raise_domain_error<T>( + "", + "Got x = %1%, but we need x > 0", x, policies::policy<>()); + } + T I, K; + bessel_ik(v, x, &I, &K, 0xFFFF, policies::policy<>()); + + std::cout << progress++ << ": K(" << v << ", " << x << ") = " << K << std::endl; + + if(fabs(K) > 1e30) + throw std::domain_error(""); + + return K; +} + +template <class T> +T cyl_neumann_bare(T v, T x) +{ + T j, y; + bessel_jy(v, x, &j, &y, 0xFFFF, policies::policy<>()); + + std::cout << progress++ << ": Y(" << v << ", " << x << ") = " << y << std::endl; + + if(fabs(y) > 1e30) + throw std::domain_error(""); + + return y; +} + +template <class T> +T sph_bessel_j_bare(T v, T x) +{ + std::cout << progress++ << ": j(" << v << ", " << x << ") = "; + if((v < 0) || (floor(v) != v)) + throw std::domain_error(""); + T r = sqrt(constants::pi<T>() / (2 * x)) * cyl_bessel_j_bare(v+0.5, x); + std::cout << r << std::endl; + return r; +} + +template <class T> +T sph_bessel_y_bare(T v, T x) +{ + std::cout << progress++ << ": y(" << v << ", " << x << ") = "; + if((v < 0) || (floor(v) != v)) + throw std::domain_error(""); + T r = sqrt(constants::pi<T>() / (2 * x)) * cyl_neumann_bare(v+0.5, x); + std::cout << r << std::endl; + return r; +} + +enum +{ + func_J = 0, + func_Y, + func_I, + func_K, + func_j, + func_y +}; + +int main(int argc, char* argv[]) +{ + std::cout << std::setprecision(17) << std::scientific; + std::cout << sph_bessel_j_bare(0., 0.1185395751953125e4) << std::endl; + std::cout << sph_bessel_j_bare(22., 0.6540834903717041015625) << std::endl; + + std::cout << std::setprecision(40) << std::scientific; + + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + int functype = 0; + std::string letter = "J"; + + if(argc == 2) + { + if(std::strcmp(argv[1], "--Y") == 0) + { + functype = func_Y; + letter = "Y"; + } + else if(std::strcmp(argv[1], "--I") == 0) + { + functype = func_I; + letter = "I"; + } + else if(std::strcmp(argv[1], "--K") == 0) + { + functype = func_K; + letter = "K"; + } + else if(std::strcmp(argv[1], "--j") == 0) + { + functype = func_j; + letter = "j"; + } + else if(std::strcmp(argv[1], "--y") == 0) + { + functype = func_y; + letter = "y"; + } + else + BOOST_ASSERT(0); + } + + bool cont; + std::string line; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the Bessel " << letter << " function\n\n"; + do{ + get_user_parameter_info(arg1, "v"); + get_user_parameter_info(arg2, "x"); + mp_t (*fp)(mp_t, mp_t); + if(functype == func_J) + fp = cyl_bessel_j_bare; + else if(functype == func_I) + fp = cyl_bessel_i_bare; + else if(functype == func_K) + fp = cyl_bessel_k_bare; + else if(functype == func_Y) + fp = cyl_neumann_bare; + else if(functype == func_j) + fp = sph_bessel_j_bare; + else if(functype == func_y) + fp = sph_bessel_y_bare; + else + BOOST_ASSERT(0); + + data.insert(fp, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=bessel_j_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "bessel_j_data.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + + + diff --git a/src/boost/libs/math/tools/bessel_derivative_append_negative.cpp b/src/boost/libs/math/tools/bessel_derivative_append_negative.cpp new file mode 100644 index 00000000..c55f3f9d --- /dev/null +++ b/src/boost/libs/math/tools/bessel_derivative_append_negative.cpp @@ -0,0 +1,305 @@ +// Copyright (c) 2014 Anton Bikineev +// 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) +// +// Appends negative test cases to the *.ipp files. +// Takes the next parameters: +// -f <file> file where the negative values will be appended; +// -x add minus to existing x values and append result; +// -v, -xv like previous option. +// Usage example: +// ./bessel_derivative_append_negative -f "bessel_y_derivative_large_data.ipp" -x -v -xv + +#include <fstream> +#include <utility> +#include <functional> +#include <map> +#include <vector> +#include <iterator> +#include <algorithm> + +#include <boost/multiprecision/mpfr.hpp> +#include <boost/program_options.hpp> +#include <boost/lexical_cast.hpp> + +#include <boost/math/special_functions/bessel.hpp> + +template <class T> +T bessel_j_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_bessel_j(v, x) - boost::math::cyl_bessel_j(v+1, x); +} + +template <class T> +T bessel_y_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_neumann(v, x) - boost::math::cyl_neumann(v+1, x); +} + +template <class T> +T bessel_i_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_bessel_i(v, x) + boost::math::cyl_bessel_i(v+1, x); +} + +template <class T> +T bessel_k_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_bessel_k(v, x) - boost::math::cyl_bessel_k(v+1, x); +} + +template <class T> +T sph_bessel_j_derivative_bare(T v, T x) +{ + if((v < 0) || (floor(v) != v)) + throw std::domain_error(""); + if(v == 0) + return -boost::math::sph_bessel(1, x); + return boost::math::sph_bessel(itrunc(v-1), x) - ((v + 1) / x) * boost::math::sph_bessel(itrunc(v), x); +} + +template <class T> +T sph_bessel_y_derivative_bare(T v, T x) +{ + if((v < 0) || (floor(v) != v)) + throw std::domain_error(""); + if(v == 0) + return -boost::math::sph_neumann(1, x); + return boost::math::sph_neumann(itrunc(v-1), x) - ((v + 1) / x) * boost::math::sph_neumann(itrunc(v), x); +} + +namespace opt = boost::program_options; +using FloatType = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<200u> >; +using Function = FloatType(*)(FloatType, FloatType); +using Lines = std::vector<std::string>; + +enum class Negate: char +{ + x, + v, + xv +}; + +namespace +{ + +const unsigned kSignificand = 50u; + +std::map<std::string, Function> kFileMapper = { + {"bessel_j_derivative_data.ipp", ::bessel_j_derivative_bare}, + {"bessel_j_derivative_int_data.ipp", ::bessel_j_derivative_bare}, + {"bessel_j_derivative_large_data.ipp", ::bessel_j_derivative_bare}, + {"bessel_y01_derivative_data.ipp", ::bessel_y_derivative_bare}, + {"bessel_yn_derivative_data.ipp", ::bessel_y_derivative_bare}, + {"bessel_yv_derivative_data.ipp", ::bessel_y_derivative_bare}, + {"bessel_i_derivative_data.ipp", ::bessel_i_derivative_bare}, + {"bessel_i_derivative_int_data.ipp", ::bessel_i_derivative_bare}, + {"bessel_k_derivative_data.ipp", ::bessel_k_derivative_bare}, + {"bessel_k_derivative_int_data.ipp", ::bessel_k_derivative_bare}, + {"sph_bessel_derivative_data.ipp", ::sph_bessel_j_derivative_bare}, + {"sph_neumann_derivative_data.ipp", ::sph_bessel_y_derivative_bare} +}; + +Function fp = ::bessel_j_derivative_bare; + +Lines getSourcePartOfFile(std::fstream& file) +{ + file.seekg(std::ios::beg); + + Lines lines; + while (true) + { + auto line = std::string{}; + std::getline(file, line); + if (line.find("}};") != std::string::npos) + break; + lines.push_back(line); + } + file.seekg(std::ios::beg); + return lines; +} + +std::pair<std::string, std::string::iterator> parseValue(std::string::iterator& iter) +{ + using std::isdigit; + + auto value = std::string{}; + auto iterator = std::string::iterator{}; + + while (!isdigit(*iter) && *iter != '-') + ++iter; + iterator = iter; + while (isdigit(*iter) || *iter == '.' || *iter == 'e' || *iter == '-' || *iter == '+') + { + value.push_back(*iter); + ++iter; + } + return {value, iterator}; +} + +void addMinusToValue(std::string& line, Negate which) +{ + using std::isdigit; + + auto iter = line.begin(); + switch (which) + { + case Negate::x: + { + ::parseValue(iter); + auto value_begin = ::parseValue(iter).second; + if (*value_begin != '-') + line.insert(value_begin, '-'); + break; + } + case Negate::v: + { + auto value_begin = ::parseValue(iter).second; + if (*value_begin != '-') + line.insert(value_begin, '-'); + break; + } + case Negate::xv: + { + auto v_value_begin = ::parseValue(iter).second; + if (*v_value_begin != '-') + line.insert(v_value_begin, '-'); + // iterator could get invalid + iter = line.begin(); + ::parseValue(iter); + auto x_value_begin = ::parseValue(iter).second; + if (*x_value_begin != '-') + line.insert(x_value_begin, '-'); + break; + } + } +} + +void replaceResultInLine(std::string& line) +{ + using std::isdigit; + + auto iter = line.begin(); + + // parse v and x values from line and convert them to FloatType + auto v = FloatType{::parseValue(iter).first}; + auto x = FloatType{::parseValue(iter).first}; + auto result = fp(v, x).str(kSignificand); + + while (!isdigit(*iter) && *iter != '-') + ++iter; + const auto where_to_write = iter; + while (isdigit(*iter) || *iter == '.' || *iter == 'e' || *iter == '-' || *iter == '+') + line.erase(iter); + + line.insert(where_to_write, result.begin(), result.end()); +} + +Lines processValues(const Lines& source_lines, Negate which) +{ + using std::placeholders::_1; + + auto processed_lines = source_lines; + std::for_each(std::begin(processed_lines), std::end(processed_lines), std::bind(&addMinusToValue, _1, which)); + std::for_each(std::begin(processed_lines), std::end(processed_lines), &replaceResultInLine); + + return processed_lines; +} + +void updateTestCount(Lines& source_lines, std::size_t mult) +{ + using std::isdigit; + + const auto where = std::find_if(std::begin(source_lines), std::end(source_lines), + [](const std::string& str){ return str.find("boost::array") != std::string::npos; }); + auto& str = *where; + const auto pos = str.find(">, ") + 3; + auto digits_length = 0; + + auto k = pos; + while (isdigit(str[k++])) + ++digits_length; + + const auto new_value = mult * boost::lexical_cast<std::size_t>(str.substr(pos, digits_length)); + str.replace(pos, digits_length, boost::lexical_cast<std::string>(new_value)); +} + +} // namespace + +int main(int argc, char*argv []) +{ + auto desc = opt::options_description{"All options"}; + desc.add_options() + ("help", "produce help message") + ("file", opt::value<std::string>()->default_value("bessel_j_derivative_data.ipp")) + ("x", "append negative x") + ("v", "append negative v") + ("xv", "append negative x and v"); + opt::variables_map vm; + opt::store(opt::command_line_parser(argc, argv).options(desc) + .style(opt::command_line_style::default_style | + opt::command_line_style::allow_long_disguise) + .run(),vm); + opt::notify(vm); + + if (vm.count("help")) + { + std::cout << desc; + return 0; + } + + auto filename = vm["file"].as<std::string>(); + fp = kFileMapper[filename]; + + std::fstream file{filename.c_str()}; + if (!file.is_open()) + return -1; + auto source_part = ::getSourcePartOfFile(file); + source_part.back().push_back(','); + + auto cases_lines = Lines{}; + for (const auto& str: source_part) + { + if (str.find("SC_") != std::string::npos) + cases_lines.push_back(str); + } + + auto new_lines = Lines{}; + new_lines.reserve(cases_lines.size()); + + std::size_t mult = 1; + if (vm.count("x")) + { + std::cout << "process x..." << std::endl; + const auto x_lines = ::processValues(cases_lines, Negate::x); + new_lines.insert(std::end(new_lines), std::begin(x_lines), std::end(x_lines)); + ++mult; + } + if (vm.count("v")) + { + std::cout << "process v..." << std::endl; + const auto v_lines = ::processValues(cases_lines, Negate::v); + new_lines.insert(std::end(new_lines), std::begin(v_lines), std::end(v_lines)); + ++mult; + } + if (vm.count("xv")) + { + std::cout << "process xv..." << std::endl; + const auto xv_lines = ::processValues(cases_lines, Negate::xv); + new_lines.insert(std::end(new_lines), std::begin(xv_lines), std::end(xv_lines)); + ++mult; + } + + source_part.insert(std::end(source_part), std::begin(new_lines), std::end(new_lines)); + ::updateTestCount(source_part, mult); + + file.close(); + file.open(filename, std::ios::out | std::ios::trunc); + std::for_each(std::begin(source_part), std::end(source_part), [&file](const std::string& str) + { file << str << std::endl; }); + file << " }};"; + + std::cout << "processed, ok\n"; + return 0; +} diff --git a/src/boost/libs/math/tools/bessel_derivative_data.cpp b/src/boost/libs/math/tools/bessel_derivative_data.cpp new file mode 100644 index 00000000..67200203 --- /dev/null +++ b/src/boost/libs/math/tools/bessel_derivative_data.cpp @@ -0,0 +1,166 @@ +// Copyright (c) 2014 Anton Bikineev +// 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) +// +// Computes test data for the derivatives of the +// various bessel functions. Results of derivatives +// are generated by the relations between the derivatives +// and Bessel functions, which actual implementation +// doesn't use. Results are printed to ~ 50 digits. +// +#include <fstream> + +#include <boost/multiprecision/mpfr.hpp> +#include <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> + +#include <boost/math/special_functions/bessel.hpp> + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; +using namespace boost::multiprecision; + +template <class T> +T bessel_j_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_bessel_j(v, x) - boost::math::cyl_bessel_j(v+1, x); +} + +template <class T> +T bessel_y_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_neumann(v, x) - boost::math::cyl_neumann(v+1, x); +} + +template <class T> +T bessel_i_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_bessel_i(v, x) + boost::math::cyl_bessel_i(v+1, x); +} + +template <class T> +T bessel_k_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_bessel_k(v, x) - boost::math::cyl_bessel_k(v+1, x); +} + +template <class T> +T sph_bessel_j_derivative_bare(T v, T x) +{ + if((v < 0) || (floor(v) != v)) + throw std::domain_error(""); + if(v == 0) + return -boost::math::sph_bessel(1, x); + return boost::math::sph_bessel(itrunc(v-1), x) - ((v + 1) / x) * boost::math::sph_bessel(itrunc(v), x); +} + +template <class T> +T sph_bessel_y_derivative_bare(T v, T x) +{ + if((v < 0) || (floor(v) != v)) + throw std::domain_error(""); + if(v == 0) + return -boost::math::sph_neumann(1, x); + return boost::math::sph_neumann(itrunc(v-1), x) - ((v + 1) / x) * boost::math::sph_neumann(itrunc(v), x); +} + +enum +{ + func_J = 0, + func_Y, + func_I, + func_K, + func_j, + func_y +}; + +int cpp_main(int argc, char*argv []) +{ + typedef number<mpfr_float_backend<200> > bignum; + + parameter_info<bignum> arg1, arg2; + test_data<bignum> data; + + int functype = 0; + std::string letter = "J"; + + if(argc == 2) + { + if(std::strcmp(argv[1], "--Y") == 0) + { + functype = func_Y; + letter = "Y"; + } + else if(std::strcmp(argv[1], "--I") == 0) + { + functype = func_I; + letter = "I"; + } + else if(std::strcmp(argv[1], "--K") == 0) + { + functype = func_K; + letter = "K"; + } + else if(std::strcmp(argv[1], "--j") == 0) + { + functype = func_j; + letter = "j"; + } + else if(std::strcmp(argv[1], "--y") == 0) + { + functype = func_y; + letter = "y"; + } + else + BOOST_ASSERT(0); + } + + bool cont; + std::string line; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the Bessel " << letter << " function derivative\n\n"; + do{ + if(0 == get_user_parameter_info(arg1, "a")) + return 1; + if(0 == get_user_parameter_info(arg2, "b")) + return 1; + + bignum (*fp)(bignum, bignum) = 0; + if(functype == func_J) + fp = bessel_j_derivative_bare; + else if(functype == func_I) + fp = bessel_i_derivative_bare; + else if(functype == func_K) + fp = bessel_k_derivative_bare; + else if(functype == func_Y) + fp = bessel_y_derivative_bare; + else if(functype == func_j) + fp = sph_bessel_j_derivative_bare; + else if(functype == func_y) + fp = sph_bessel_y_derivative_bare; + else + BOOST_ASSERT(0); + + data.insert(fp, arg2, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=bessel_j_derivative_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "bessel_j_derivative_data.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(50); + write_code(ofs, data, line.c_str()); + + return 0; +} diff --git a/src/boost/libs/math/tools/bessel_derivative_data_from_bessel_ipps.cpp b/src/boost/libs/math/tools/bessel_derivative_data_from_bessel_ipps.cpp new file mode 100644 index 00000000..fb9f6f38 --- /dev/null +++ b/src/boost/libs/math/tools/bessel_derivative_data_from_bessel_ipps.cpp @@ -0,0 +1,213 @@ +// Copyright (c) 2014 Anton Bikineev +// 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) +// +// Computes test data for the derivatives of the +// various bessel functions. v and x parameters are taken +// from bessel_*_data.ipp files. Results of derivatives +// are generated by the relations between the derivatives +// and Bessel functions, which actual implementation +// doesn't use. Results are printed to ~ 50 digits. +// +#include <fstream> +#include <utility> +#include <map> +#include <iterator> +#include <algorithm> + +#include <boost/multiprecision/mpfr.hpp> + +#include <boost/math/special_functions/bessel.hpp> + +template <class T> +T bessel_j_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_bessel_j(v, x) - boost::math::cyl_bessel_j(v+1, x); +} + +template <class T> +T bessel_y_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_neumann(v, x) - boost::math::cyl_neumann(v+1, x); +} + +template <class T> +T bessel_i_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_bessel_i(v, x) + boost::math::cyl_bessel_i(v+1, x); +} + +template <class T> +T bessel_k_derivative_bare(T v, T x) +{ + return (v / x) * boost::math::cyl_bessel_k(v, x) - boost::math::cyl_bessel_k(v+1, x); +} + +template <class T> +T sph_bessel_j_derivative_bare(T v, T x) +{ + if((v < 0) || (floor(v) != v)) + throw std::domain_error(""); + if(v == 0) + return -boost::math::sph_bessel(1, x); + return boost::math::sph_bessel(itrunc(v-1), x) - ((v + 1) / x) * boost::math::sph_bessel(itrunc(v), x); +} + +template <class T> +T sph_bessel_y_derivative_bare(T v, T x) +{ + if((v < 0) || (floor(v) != v)) + throw std::domain_error(""); + if(v == 0) + return -boost::math::sph_neumann(1, x); + return boost::math::sph_neumann(itrunc(v-1), x) - ((v + 1) / x) * boost::math::sph_neumann(itrunc(v), x); +} + +using FloatType = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<200u> >; + +enum class BesselFamily: char +{ + J = 0, + Y, + I, + K, + j, + y +}; + +namespace +{ + +const unsigned kSignificand = 50u; + +const std::map<BesselFamily, std::vector<std::string> > kSourceFiles = { + {BesselFamily::J, {"bessel_j_data.ipp", "bessel_j_int_data.ipp", "bessel_j_large_data.ipp"}}, + {BesselFamily::Y, {"bessel_y01_data.ipp", "bessel_yn_data.ipp", "bessel_yv_data.ipp"}}, + {BesselFamily::I, {"bessel_i_data.ipp", "bessel_i_int_data.ipp"}}, + {BesselFamily::K, {"bessel_k_data.ipp", "bessel_k_int_data.ipp"}}, + {BesselFamily::j, {"sph_bessel_data.ipp"}}, + {BesselFamily::y, {"sph_neumann_data.ipp"}} +}; + +FloatType (*fp)(FloatType, FloatType) = ::bessel_j_derivative_bare; + +std::string parseValue(std::string::iterator& iter) +{ + using std::isdigit; + + auto value = std::string{}; + + while (!isdigit(*iter) && *iter != '-') + ++iter; + while (isdigit(*iter) || *iter == '.' || *iter == 'e' || *iter == '-' || *iter == '+') + { + value.push_back(*iter); + ++iter; + } + return value; +} + +void replaceResultInLine(std::string& line) +{ + using std::isdigit; + + auto iter = line.begin(); + + // parse v and x values from line and convert them to FloatType + auto v = FloatType{::parseValue(iter)}; + auto x = FloatType{::parseValue(iter)}; + auto result = fp(v, x).str(kSignificand); + + while (!isdigit(*iter) && *iter != '-') + ++iter; + const auto where_to_write = iter; + while (isdigit(*iter) || *iter == '.' || *iter == 'e' || *iter == '-' || *iter == '+') + line.erase(iter); + + line.insert(where_to_write, result.begin(), result.end()); +} + +void generateResultFile(const std::string& i_file, const std::string& o_file) +{ + std::ifstream in{i_file.c_str()}; + std::ofstream out{o_file.c_str()}; + + auto line = std::string{}; + while (!in.eof()) + { + std::getline(in, line); + if (__builtin_expect(line.find("SC_") != std::string::npos, 1)) + ::replaceResultInLine(line); + out << line << std::endl; + } +} + +void processFiles(BesselFamily family) +{ + const auto& family_files = kSourceFiles.find(family)->second; + + std::for_each(std::begin(family_files), std::end(family_files), + [&](const std::string& src){ + auto new_file = src; + + const auto int_pos = new_file.find("int"); + const auto large_pos = new_file.find("large"); + const auto data_pos = new_file.find("data"); + const auto derivative_pos = (int_pos == std::string::npos ? + (large_pos == std::string::npos ? data_pos : large_pos) : + int_pos); + + new_file.insert(derivative_pos, "derivative_"); + + ::generateResultFile(src, new_file); + }); +} + +} // namespace + +int main(int argc, char*argv []) +{ + auto functype = BesselFamily::J; + auto letter = std::string{"J"}; + + if(argc == 2) + { + if(std::strcmp(argv[1], "--Y") == 0) + { + functype = BesselFamily::Y; + fp = ::bessel_y_derivative_bare; + letter = "Y"; + } + else if(std::strcmp(argv[1], "--I") == 0) + { + functype = BesselFamily::I; + fp = ::bessel_i_derivative_bare; + letter = "I"; + } + else if(std::strcmp(argv[1], "--K") == 0) + { + functype = BesselFamily::K; + fp = ::bessel_k_derivative_bare; + letter = "K"; + } + else if(std::strcmp(argv[1], "--j") == 0) + { + functype = BesselFamily::j; + fp = ::sph_bessel_j_derivative_bare; + letter = "j"; + } + else if(std::strcmp(argv[1], "--y") == 0) + { + functype = BesselFamily::y; + fp = ::sph_bessel_y_derivative_bare; + letter = "y"; + } + else + BOOST_ASSERT(0); + } + + ::processFiles(functype); + + return 0; +} diff --git a/src/boost/libs/math/tools/beta_data.cpp b/src/boost/libs/math/tools/beta_data.cpp new file mode 100644 index 00000000..2ab3336d --- /dev/null +++ b/src/boost/libs/math/tools/beta_data.cpp @@ -0,0 +1,68 @@ +// (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 <boost/math/special_functions/gamma.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/math/tools/test_data.hpp> +#include <fstream> +#include "mp_t.hpp" + +using namespace boost::math::tools; + +struct beta_data_generator +{ + mp_t operator()(mp_t a, mp_t b) + { + if(a < b) + throw std::domain_error(""); + // very naively calculate spots: + mp_t g1, g2, g3; + int s1, s2, s3; + g1 = boost::math::lgamma(a, &s1); + g2 = boost::math::lgamma(b, &s2); + g3 = boost::math::lgamma(a+b, &s3); + g1 += g2 - g3; + g1 = exp(g1); + g1 *= s1 * s2 * s3; + return g1; + } +}; + + +int main() +{ + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the beta function:\n" + " beta(a, b)\n\n"; + + bool cont; + std::string line; + + do{ + get_user_parameter_info(arg1, "a"); + get_user_parameter_info(arg2, "b"); + data.insert(beta_data_generator(), arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=beta_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "beta_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "beta_data"); + + return 0; +} + diff --git a/src/boost/libs/math/tools/carlson_ellint_data.cpp b/src/boost/libs/math/tools/carlson_ellint_data.cpp new file mode 100644 index 00000000..5bd98073 --- /dev/null +++ b/src/boost/libs/math/tools/carlson_ellint_data.cpp @@ -0,0 +1,630 @@ +// 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 <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <boost/math/special_functions/ellint_rj.hpp> +#include <boost/math/special_functions/ellint_rd.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +float extern_val; +// confuse the compilers optimiser, and force a truncation to float precision: +float truncate_to_float(float const * pf) +{ + extern_val = *pf; + return *pf; +} + +// +// Archived here is the original implementation of this +// function by Xiaogang Zhang, we can use this to +// generate special test cases for the new version: +// +template <typename T, typename Policy> +T ellint_rj_old(T x, T y, T z, T p, const Policy& pol) +{ + T value, u, lambda, alpha, beta, sigma, factor, tolerance; + T X, Y, Z, P, EA, EB, EC, E2, E3, S1, S2, S3; + unsigned long k; + + BOOST_MATH_STD_USING + using namespace boost::math; + + static const char* function = "boost::math::ellint_rj<%1%>(%1%,%1%,%1%)"; + + if(x < 0) + { + return policies::raise_domain_error<T>(function, + "Argument x must be non-negative, but got x = %1%", x, pol); + } + if(y < 0) + { + return policies::raise_domain_error<T>(function, + "Argument y must be non-negative, but got y = %1%", y, pol); + } + if(z < 0) + { + return policies::raise_domain_error<T>(function, + "Argument z must be non-negative, but got z = %1%", z, pol); + } + if(p == 0) + { + return policies::raise_domain_error<T>(function, + "Argument p must not be zero, but got p = %1%", p, pol); + } + if(x + y == 0 || y + z == 0 || z + x == 0) + { + return policies::raise_domain_error<T>(function, + "At most one argument can be zero, " + "only possible result is %1%.", std::numeric_limits<T>::quiet_NaN(), pol); + } + + // error scales as the 6th power of tolerance + tolerance = pow(T(1) * tools::epsilon<T>() / 3, T(1) / 6); + + // for p < 0, the integral is singular, return Cauchy principal value + if(p < 0) + { + // + // We must ensure that (z - y) * (y - x) is positive. + // Since the integral is symmetrical in x, y and z + // we can just permute the values: + // + if(x > y) + std::swap(x, y); + if(y > z) + std::swap(y, z); + if(x > y) + std::swap(x, y); + + T q = -p; + T pmy = (z - y) * (y - x) / (y + q); // p - y + + BOOST_ASSERT(pmy >= 0); + + p = pmy + y; + value = ellint_rj_old(x, y, z, p, pol); + value *= pmy; + value -= 3 * boost::math::ellint_rf(x, y, z, pol); + value += 3 * sqrt((x * y * z) / (x * z + p * q)) * boost::math::ellint_rc(x * z + p * q, p * q, pol); + value /= (y + q); + return value; + } + + // duplication + sigma = 0; + factor = 1; + k = 1; + do + { + u = (x + y + z + p + p) / 5; + X = (u - x) / u; + Y = (u - y) / u; + Z = (u - z) / u; + P = (u - p) / u; + + if((tools::max)(abs(X), abs(Y), abs(Z), abs(P)) < tolerance) + break; + + T sx = sqrt(x); + T sy = sqrt(y); + T sz = sqrt(z); + + lambda = sy * (sx + sz) + sz * sx; + alpha = p * (sx + sy + sz) + sx * sy * sz; + alpha *= alpha; + beta = p * (p + lambda) * (p + lambda); + sigma += factor * boost::math::ellint_rc(alpha, beta, pol); + factor /= 4; + x = (x + lambda) / 4; + y = (y + lambda) / 4; + z = (z + lambda) / 4; + p = (p + lambda) / 4; + ++k; + } while(k < policies::get_max_series_iterations<Policy>()); + + // Check to see if we gave up too soon: + policies::check_series_iterations<T>(function, k, pol); + + // Taylor series expansion to the 5th order + EA = X * Y + Y * Z + Z * X; + EB = X * Y * Z; + EC = P * P; + E2 = EA - 3 * EC; + E3 = EB + 2 * P * (EA - EC); + S1 = 1 + E2 * (E2 * T(9) / 88 - E3 * T(9) / 52 - T(3) / 14); + S2 = EB * (T(1) / 6 + P * (T(-6) / 22 + P * T(3) / 26)); + S3 = P * ((EA - EC) / 3 - P * EA * T(3) / 22); + value = 3 * sigma + factor * (S1 + S2 + S3) / (u * sqrt(u)); + + return value; +} + +template <typename T, typename Policy> +T ellint_rd_imp_old(T x, T y, T z, const Policy& pol) +{ + T value, u, lambda, sigma, factor, tolerance; + T X, Y, Z, EA, EB, EC, ED, EE, S1, S2; + unsigned long k; + + BOOST_MATH_STD_USING + using namespace boost::math; + + static const char* function = "boost::math::ellint_rd<%1%>(%1%,%1%,%1%)"; + + if(x < 0) + { + return policies::raise_domain_error<T>(function, + "Argument x must be >= 0, but got %1%", x, pol); + } + if(y < 0) + { + return policies::raise_domain_error<T>(function, + "Argument y must be >= 0, but got %1%", y, pol); + } + if(z <= 0) + { + return policies::raise_domain_error<T>(function, + "Argument z must be > 0, but got %1%", z, pol); + } + if(x + y == 0) + { + return policies::raise_domain_error<T>(function, + "At most one argument can be zero, but got, x + y = %1%", x + y, pol); + } + + // error scales as the 6th power of tolerance + tolerance = pow(tools::epsilon<T>() / 3, T(1) / 6); + + // duplication + sigma = 0; + factor = 1; + k = 1; + do + { + u = (x + y + z + z + z) / 5; + X = (u - x) / u; + Y = (u - y) / u; + Z = (u - z) / u; + if((tools::max)(abs(X), abs(Y), abs(Z)) < tolerance) + break; + T sx = sqrt(x); + T sy = sqrt(y); + T sz = sqrt(z); + lambda = sy * (sx + sz) + sz * sx; //sqrt(x * y) + sqrt(y * z) + sqrt(z * x); + sigma += factor / (sz * (z + lambda)); + factor /= 4; + x = (x + lambda) / 4; + y = (y + lambda) / 4; + z = (z + lambda) / 4; + ++k; + } while(k < policies::get_max_series_iterations<Policy>()); + + // Check to see if we gave up too soon: + policies::check_series_iterations<T>(function, k, pol); + + // Taylor series expansion to the 5th order + EA = X * Y; + EB = Z * Z; + EC = EA - EB; + ED = EA - 6 * EB; + EE = ED + EC + EC; + S1 = ED * (ED * T(9) / 88 - Z * EE * T(9) / 52 - T(3) / 14); + S2 = Z * (EE / 6 + Z * (-EC * T(9) / 22 + Z * EA * T(3) / 26)); + value = 3 * sigma + factor * (1 + S1 + S2) / (u * sqrt(u)); + + return value; +} + +template <typename T, typename Policy> +T ellint_rf_imp_old(T x, T y, T z, const Policy& pol) +{ + T value, X, Y, Z, E2, E3, u, lambda, tolerance; + unsigned long k; + BOOST_MATH_STD_USING + using namespace boost::math; + static const char* function = "boost::math::ellint_rf<%1%>(%1%,%1%,%1%)"; + if(x < 0 || y < 0 || z < 0) + { + return policies::raise_domain_error<T>(function, + "domain error, all arguments must be non-negative, " + "only sensible result is %1%.", + std::numeric_limits<T>::quiet_NaN(), pol); + } + if(x + y == 0 || y + z == 0 || z + x == 0) + { + return policies::raise_domain_error<T>(function, + "domain error, at most one argument can be zero, " + "only sensible result is %1%.", + std::numeric_limits<T>::quiet_NaN(), pol); + } + // Carlson scales error as the 6th power of tolerance, + // but this seems not to work for types larger than + // 80-bit reals, this heuristic seems to work OK: + if(policies::digits<T, Policy>() > 64) + { + tolerance = pow(tools::epsilon<T>(), T(1) / 4.25f); + BOOST_MATH_INSTRUMENT_VARIABLE(tolerance); + } + else + { + tolerance = pow(4 * tools::epsilon<T>(), T(1) / 6); + BOOST_MATH_INSTRUMENT_VARIABLE(tolerance); + } + // duplication + k = 1; + do + { + u = (x + y + z) / 3; + X = (u - x) / u; + Y = (u - y) / u; + Z = (u - z) / u; + // Termination condition: + if((tools::max)(abs(X), abs(Y), abs(Z)) < tolerance) + break; + T sx = sqrt(x); + T sy = sqrt(y); + T sz = sqrt(z); + lambda = sy * (sx + sz) + sz * sx; + x = (x + lambda) / 4; + y = (y + lambda) / 4; + z = (z + lambda) / 4; + ++k; + } while(k < policies::get_max_series_iterations<Policy>()); + // Check to see if we gave up too soon: + policies::check_series_iterations<T>(function, k, pol); + BOOST_MATH_INSTRUMENT_VARIABLE(k); + // Taylor series expansion to the 5th order + E2 = X * Y - Z * Z; + E3 = X * Y * Z; + value = (1 + E2*(E2 / 24 - E3*T(3) / 44 - T(0.1)) + E3 / 14) / sqrt(u); + BOOST_MATH_INSTRUMENT_VARIABLE(value); + return value; +} + + + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rj_data_4e(mp_t n) +{ + mp_t result = ellint_rj_old(n, n, n, n, boost::math::policies::policy<>()); + return boost::math::make_tuple(n, n, n, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t> generate_rj_data_3e(mp_t x, mp_t p) +{ + mp_t r = ellint_rj_old(x, x, x, p, boost::math::policies::policy<>()); + return boost::math::make_tuple(x, x, x, p, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t> generate_rj_data_2e_1(mp_t x, mp_t y, mp_t p) +{ + mp_t r = ellint_rj_old(x, x, y, p, boost::math::policies::policy<>()); + return boost::math::make_tuple(x, x, y, p, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t> generate_rj_data_2e_2(mp_t x, mp_t y, mp_t p) +{ + mp_t r = ellint_rj_old(x, y, x, p, boost::math::policies::policy<>()); + return boost::math::make_tuple(x, y, x, p, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t> generate_rj_data_2e_3(mp_t x, mp_t y, mp_t p) +{ + mp_t r = ellint_rj_old(y, x, x, p, boost::math::policies::policy<>()); + return boost::math::make_tuple(y, x, x, p, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t> generate_rj_data_2e_4(mp_t x, mp_t y, mp_t p) +{ + mp_t r = ellint_rj_old(x, y, p, p, boost::math::policies::policy<>()); + return boost::math::make_tuple(x, y, p, p, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rd_data_2e_1(mp_t x, mp_t y) +{ + mp_t r = ellint_rd_imp_old(x, y, y, boost::math::policies::policy<>()); + return boost::math::make_tuple(x, y, y, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rd_data_2e_2(mp_t x, mp_t y) +{ + mp_t r = ellint_rd_imp_old(x, x, y, boost::math::policies::policy<>()); + return boost::math::make_tuple(x, x, y, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rd_data_2e_3(mp_t x) +{ + mp_t r = ellint_rd_imp_old(mp_t(0), x, x, boost::math::policies::policy<>()); + return boost::math::make_tuple(0, x, x, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rd_data_3e(mp_t x) +{ + mp_t r = ellint_rd_imp_old(x, x, x, boost::math::policies::policy<>()); + return boost::math::make_tuple(x, x, x, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rd_data_0xy(mp_t x, mp_t y) +{ + mp_t r = ellint_rd_imp_old(mp_t(0), x, y, boost::math::policies::policy<>()); + return boost::math::make_tuple(mp_t(0), x, y, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rf_data_xxx(mp_t x) +{ + mp_t r = ellint_rf_imp_old(x, x, x, boost::math::policies::policy<>()); + return boost::math::make_tuple(x, x, x, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rf_data_xyy(mp_t x, mp_t y) +{ + mp_t r = ellint_rf_imp_old(x, y, y, boost::math::policies::policy<>()); + return boost::math::make_tuple(x, y, y, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rf_data_xxy(mp_t x, mp_t y) +{ + mp_t r = ellint_rf_imp_old(x, x, y, boost::math::policies::policy<>()); + return boost::math::make_tuple(x, x, y, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rf_data_xyx(mp_t x, mp_t y) +{ + mp_t r = ellint_rf_imp_old(x, y, x, boost::math::policies::policy<>()); + return boost::math::make_tuple(x, y, x, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rf_data_0yy(mp_t y) +{ + mp_t r = ellint_rf_imp_old(mp_t(0), y, y, boost::math::policies::policy<>()); + return boost::math::make_tuple(mp_t(0), y, y, r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rf_data_xy0(mp_t x, mp_t y) +{ + mp_t r = ellint_rf_imp_old(x, y, mp_t(0), boost::math::policies::policy<>()); + return boost::math::make_tuple(x, y, mp_t(0), r); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rf_data(mp_t n) +{ + static boost::mt19937 r; + boost::uniform_real<float> ur(0, 1); + boost::uniform_int<int> ui(-100, 100); + float x = ur(r); + x = ldexp(x, ui(r)); + mp_t xr(truncate_to_float(&x)); + float y = ur(r); + y = ldexp(y, ui(r)); + mp_t yr(truncate_to_float(&y)); + float z = ur(r); + z = ldexp(z, ui(r)); + mp_t zr(truncate_to_float(&z)); + + mp_t result = boost::math::ellint_rf(xr, yr, zr); + return boost::math::make_tuple(xr, yr, zr, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t> generate_rc_data(mp_t n) +{ + static boost::mt19937 r; + boost::uniform_real<float> ur(0, 1); + boost::uniform_int<int> ui(-100, 100); + float x = ur(r); + x = ldexp(x, ui(r)); + mp_t xr(truncate_to_float(&x)); + float y = ur(r); + y = ldexp(y, ui(r)); + mp_t yr(truncate_to_float(&y)); + + mp_t result = boost::math::ellint_rc(xr, yr); + return boost::math::make_tuple(xr, yr, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t> generate_rj_data(mp_t n) +{ + static boost::mt19937 r; + boost::uniform_real<float> ur(0, 1); + boost::uniform_real<float> nur(-1, 1); + boost::uniform_int<int> ui(-100, 100); + float x = ur(r); + x = ldexp(x, ui(r)); + mp_t xr(truncate_to_float(&x)); + float y = ur(r); + y = ldexp(y, ui(r)); + mp_t yr(truncate_to_float(&y)); + float z = ur(r); + z = ldexp(z, ui(r)); + mp_t zr(truncate_to_float(&z)); + float p = nur(r); + p = ldexp(p, ui(r)); + mp_t pr(truncate_to_float(&p)); + + boost::math::ellint_rj(x, y, z, p); + + mp_t result = boost::math::ellint_rj(xr, yr, zr, pr); + return boost::math::make_tuple(xr, yr, zr, pr, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rd_data(mp_t n) +{ + static boost::mt19937 r; + boost::uniform_real<float> ur(0, 1); + boost::uniform_int<int> ui(-100, 100); + float x = ur(r); + x = ldexp(x, ui(r)); + mp_t xr(truncate_to_float(&x)); + float y = ur(r); + y = ldexp(y, ui(r)); + mp_t yr(truncate_to_float(&y)); + float z = ur(r); + z = ldexp(z, ui(r)); + mp_t zr(truncate_to_float(&z)); + + mp_t result = boost::math::ellint_rd(xr, yr, zr); + return boost::math::make_tuple(xr, yr, zr, result); +} + +mp_t rg_imp(mp_t x, mp_t y, mp_t z) +{ + using std::swap; + // If z is zero permute so the call to RD is valid: + if(z == 0) + swap(x, z); + return (z * ellint_rf_imp_old(x, y, z, boost::math::policies::policy<>()) + - (x - z) * (y - z) * ellint_rd_imp_old(x, y, z, boost::math::policies::policy<>()) / 3 + + sqrt(x * y / z)) / 2; +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_data(mp_t n) +{ + static boost::mt19937 r; + boost::uniform_real<float> ur(0, 1); + boost::uniform_int<int> ui(-100, 100); + float x = ur(r); + x = ldexp(x, ui(r)); + mp_t xr(truncate_to_float(&x)); + float y = ur(r); + y = ldexp(y, ui(r)); + mp_t yr(truncate_to_float(&y)); + float z = ur(r); + z = ldexp(z, ui(r)); + mp_t zr(truncate_to_float(&z)); + + mp_t result = rg_imp(xr, yr, zr); + return boost::math::make_tuple(xr, yr, zr, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_xxx(mp_t x) +{ + mp_t result = rg_imp(x, x, x); + return boost::math::make_tuple(x, x, x, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_xyy(mp_t x, mp_t y) +{ + mp_t result = rg_imp(x, y, y); + return boost::math::make_tuple(x, y, y, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_xxy(mp_t x, mp_t y) +{ + mp_t result = rg_imp(x, x, y); + return boost::math::make_tuple(x, x, y, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_xyx(mp_t x, mp_t y) +{ + mp_t result = rg_imp(x, y, x); + return boost::math::make_tuple(x, y, x, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_0xx(mp_t x) +{ + mp_t result = rg_imp(mp_t(0), x, x); + return boost::math::make_tuple(mp_t(0), x, x, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_x0x(mp_t x) +{ + mp_t result = rg_imp(x, mp_t(0), x); + return boost::math::make_tuple(x, mp_t(0), x, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_xx0(mp_t x) +{ + mp_t result = rg_imp(x, x, mp_t(0)); + return boost::math::make_tuple(x, x, mp_t(0), result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_00x(mp_t x) +{ + mp_t result = sqrt(x) / 2; + return boost::math::make_tuple(mp_t(0), mp_t(0), x, result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_0x0(mp_t x) +{ + mp_t result = sqrt(x) / 2; + return boost::math::make_tuple(mp_t(0), x, mp_t(0), result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_x00(mp_t x) +{ + mp_t result = sqrt(x) / 2; + return boost::math::make_tuple(x, mp_t(0), mp_t(0), result); +} + +boost::math::tuple<mp_t, mp_t, mp_t, mp_t> generate_rg_xy0(mp_t x, mp_t y) +{ + mp_t result = rg_imp(x, y, mp_t(0)); + return boost::math::make_tuple(x, y, mp_t(0), result); +} + +int cpp_main(int argc, char*argv[]) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ +#if 0 + int count; + std::cout << "Number of points: "; + std::cin >> count; + + arg1 = make_periodic_param(mp_t(0), mp_t(1), count); + arg1.type |= dummy_param; + + // + // Change this next line to get the R variant you want: + // + data.insert(&generate_rd_data, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); +#else + get_user_parameter_info(arg1, "x"); + get_user_parameter_info(arg2, "y"); + //get_user_parameter_info(arg3, "p"); + arg1.type |= dummy_param; + arg2.type |= dummy_param; + //arg3.type |= dummy_param; + data.insert(generate_rd_data_0xy, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); +#endif + }while(cont); + + std::cout << "Enter name of test data file [default=ellint_rf_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "ellint_rf_data.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/cbrt_data.cpp b/src/boost/libs/math/tools/cbrt_data.cpp new file mode 100644 index 00000000..95c0a46f --- /dev/null +++ b/src/boost/libs/math/tools/cbrt_data.cpp @@ -0,0 +1,64 @@ +// (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 <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace std; + +struct cube_data_generator +{ + mp_t operator()(mp_t z) + { + mp_t result = z*z*z; + // if result is out of range of a float, + // don't include in test data as it messes up our results: + if(result > (std::numeric_limits<float>::max)()) + throw std::domain_error(""); + if(result < (std::numeric_limits<float>::min)()) + throw std::domain_error(""); + return result; + } +}; + +int main(int argc, char* argv[]) +{ + parameter_info<mp_t> arg1; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the cbrt function:\n\n"; + + bool cont; + std::string line; + + do{ + if(0 == get_user_parameter_info(arg1, "z")) + return 1; + data.insert(cube_data_generator(), arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=cbrt_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "cbrt_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "cbrt_data"); + + return 0; +} + + + + diff --git a/src/boost/libs/math/tools/digamma_data.cpp b/src/boost/libs/math/tools/digamma_data.cpp new file mode 100644 index 00000000..d2f7c315 --- /dev/null +++ b/src/boost/libs/math/tools/digamma_data.cpp @@ -0,0 +1,64 @@ +// (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 <boost/math/special_functions/digamma.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace std; + +float external_f; +float force_truncate(const float* f) +{ + external_f = *f; + return external_f; +} + +float truncate_to_float(mp_t r) +{ + float f = boost::math::tools::real_cast<float>(r); + return force_truncate(&f); +} + +int cpp_main(int argc, char*argv []) +{ + parameter_info<mp_t> arg1; + test_data<mp_t> data; + + bool cont; + std::string line; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the digamma function:\n" + " digamma(z)\n\n"; + + do{ + if(0 == get_user_parameter_info(arg1, "z")) + return 1; + data.insert(&boost::math::digamma<mp_t>, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=digamma_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "digamma_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "digamma_data"); + + return 0; +} + + + diff --git a/src/boost/libs/math/tools/ellint_d2_data.cpp b/src/boost/libs/math/tools/ellint_d2_data.cpp new file mode 100644 index 00000000..79263711 --- /dev/null +++ b/src/boost/libs/math/tools/ellint_d2_data.cpp @@ -0,0 +1,64 @@ +// 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 <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <boost/math/special_functions/ellint_1.hpp> +#include <boost/math/special_functions/ellint_2.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +mp_t ellint_d(mp_t phi, mp_t k) +{ + return (boost::math::ellint_1(k, phi) - boost::math::ellint_2(k, phi)) / (k * k); +} + +int cpp_main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + if(0 == get_user_parameter_info(arg1, "phi")) + return 1; + if(0 == get_user_parameter_info(arg2, "k")) + return 1; + + mp_t(*fp)(mp_t, mp_t) = &ellint_d; + data.insert(fp, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=ellint_d2_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "ellint_d2_data.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/ellint_d_data.cpp b/src/boost/libs/math/tools/ellint_d_data.cpp new file mode 100644 index 00000000..f2c30f37 --- /dev/null +++ b/src/boost/libs/math/tools/ellint_d_data.cpp @@ -0,0 +1,62 @@ +// 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 <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <boost/math/special_functions/ellint_1.hpp> +#include <boost/math/special_functions/ellint_2.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +mp_t ellint_d(mp_t k) +{ + return (boost::math::ellint_1(k) - boost::math::ellint_2(k)) / (k * k); +} + +int cpp_main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + if(0 == get_user_parameter_info(arg1, "k")) + return 1; + + mp_t(*fp)(mp_t) = &ellint_d; + data.insert(fp, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=ellint_d_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "ellint_d_data.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/ellint_e_data.cpp b/src/boost/libs/math/tools/ellint_e_data.cpp new file mode 100644 index 00000000..d68d3f20 --- /dev/null +++ b/src/boost/libs/math/tools/ellint_e_data.cpp @@ -0,0 +1,60 @@ +// (C) Copyright John Maddock 2007. +// 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 <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <boost/math/special_functions/ellint_2.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +template<class T> +T ellint_e_data(T k) +{ + return ellint_2(k); +} + +int cpp_main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + if(0 == get_user_parameter_info(arg1, "phi")) + return 1; + + data.insert(&ellint_e_data<mp_t>, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=ellint_e_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "ellint_e_data.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + diff --git a/src/boost/libs/math/tools/ellint_f_data.cpp b/src/boost/libs/math/tools/ellint_f_data.cpp new file mode 100644 index 00000000..4ecc4f01 --- /dev/null +++ b/src/boost/libs/math/tools/ellint_f_data.cpp @@ -0,0 +1,72 @@ +// (C) Copyright John Maddock 2007. +// 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 <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <boost/math/special_functions/ellint_1.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +float extern_val; +// confuse the compilers optimiser, and force a truncation to float precision: +float truncate_to_float(float const * pf) +{ + extern_val = *pf; + return *pf; +} + + + +template<class T> +T ellint_f_data(T phi, T k) +{ + return ellint_1(k, phi); +} + +int cpp_main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + if(0 == get_user_parameter_info(arg1, "phi")) + return 1; + if(0 == get_user_parameter_info(arg2, "k")) + return 1; + + data.insert(&ellint_f_data<mp_t>, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=ellint_f.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "ellint_f.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + diff --git a/src/boost/libs/math/tools/ellint_k_data.cpp b/src/boost/libs/math/tools/ellint_k_data.cpp new file mode 100644 index 00000000..8f58cb0d --- /dev/null +++ b/src/boost/libs/math/tools/ellint_k_data.cpp @@ -0,0 +1,60 @@ +// (C) Copyright John Maddock 2007. +// 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 <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <boost/math/special_functions/ellint_1.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +template<class T> +T ellint_k_data(T k) +{ + return ellint_1(k); +} + +int cpp_main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + if(0 == get_user_parameter_info(arg1, "phi")) + return 1; + + data.insert(&ellint_k_data<mp_t>, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=ellint_k_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "ellint_k_data.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + diff --git a/src/boost/libs/math/tools/ellint_pi2_data.cpp b/src/boost/libs/math/tools/ellint_pi2_data.cpp new file mode 100644 index 00000000..e7b63ec4 --- /dev/null +++ b/src/boost/libs/math/tools/ellint_pi2_data.cpp @@ -0,0 +1,59 @@ +// 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 <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <boost/math/special_functions/ellint_2.hpp> +#include <boost/math/special_functions/ellint_3.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +int cpp_main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + if(0 == get_user_parameter_info(arg1, "n")) + return 1; + if(0 == get_user_parameter_info(arg2, "k")) + return 1; + + mp_t (*fp)(mp_t, mp_t) = &ellint_3; + data.insert(fp, arg2, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=ellint_pi2_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "ellint_pi2_data.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/ellint_pi3_data.cpp b/src/boost/libs/math/tools/ellint_pi3_data.cpp new file mode 100644 index 00000000..bc09d9cf --- /dev/null +++ b/src/boost/libs/math/tools/ellint_pi3_data.cpp @@ -0,0 +1,75 @@ +// 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 <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <boost/math/special_functions/ellint_3.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +float extern_val; +// confuse the compilers optimiser, and force a truncation to float precision: +float truncate_to_float(float const * pf) +{ + extern_val = *pf; + return *pf; +} + +boost::math::tuple<mp_t, mp_t> generate_data(mp_t n, mp_t phi) +{ + static boost::mt19937 r; + boost::uniform_real<float> ui(0, 1); + float k = ui(r); + mp_t kr(truncate_to_float(&k)); + mp_t result = boost::math::ellint_3(kr, n, phi); + return boost::math::make_tuple(kr, result); +} + +int cpp_main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + if(0 == get_user_parameter_info(arg1, "n")) + return 1; + if(0 == get_user_parameter_info(arg2, "phi")) + return 1; + + data.insert(&generate_data, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=ellint_pi3_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "ellint_pi3_data.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/erf_data.cpp b/src/boost/libs/math/tools/erf_data.cpp new file mode 100644 index 00000000..b2e76b80 --- /dev/null +++ b/src/boost/libs/math/tools/erf_data.cpp @@ -0,0 +1,218 @@ +// (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 <boost/math/special_functions/gamma.hpp> +#include <boost/math/special_functions/erf.hpp> // for inverses +#include <boost/math/constants/constants.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace std; + +float external_f; +float force_truncate(const float* f) +{ + external_f = *f; + return external_f; +} + +float truncate_to_float(mp_t r) +{ + float f = boost::math::tools::real_cast<float>(r); + return force_truncate(&f); +} + +struct erf_data_generator +{ + boost::math::tuple<mp_t, mp_t> operator()(mp_t z) + { + // very naively calculate spots using the gamma function at high precision: + int sign = 1; + if(z < 0) + { + sign = -1; + z = -z; + } + mp_t g1, g2; + g1 = boost::math::tgamma_lower(mp_t(0.5), z * z); + g1 /= sqrt(boost::math::constants::pi<mp_t>()); + g1 *= sign; + + if(z < 0.5) + { + g2 = 1 - (sign * g1); + } + else + { + g2 = boost::math::tgamma(mp_t(0.5), z * z); + g2 /= sqrt(boost::math::constants::pi<mp_t>()); + } + if(sign < 1) + g2 = 2 - g2; + return boost::math::make_tuple(g1, g2); + } +}; + +double double_factorial(int N) +{ + double result = 1; + while(N > 2) + { + N -= 2; + result *= N; + } + return result; +} + +void asymptotic_limit(int Bits) +{ + // + // The following block of code estimates how large z has + // to be before we can use the asymptotic expansion for + // erf/erfc and still get convergence: the series becomes + // divergent eventually so we have to be careful! + // + double result = (std::numeric_limits<double>::max)(); + int terms = 0; + for(int n = 1; n < 15; ++n) + { + double lim = (Bits-n) * log(2.0) - log(sqrt(3.14)) + log(double_factorial(2*n+1)); + double x = 1; + while(x*x + (2*n+1)*log(x) <= lim) + x += 0.1; + if(x < result) + { + result = x; + terms = n; + } + } + + std::cout << "Erf asymptotic limit for " + << Bits << " bit numbers is " + << result << " after approximately " + << terms << " terms." << std::endl; + + result = (std::numeric_limits<double>::max)(); + terms = 0; + for(int n = 1; n < 30; ++n) + { + double x = pow(double_factorial(2*n+1)/pow(2.0, n-Bits), 1 / (2.0*n)); + if(x < result) + { + result = x; + terms = n; + } + } + + std::cout << "Erfc asymptotic limit for " + << Bits << " bit numbers is " + << result << " after approximately " + << terms << " terms." << std::endl; +} + +boost::math::tuple<mp_t, mp_t> erfc_inv(mp_t r) +{ + mp_t x = exp(-r * r); + x = x.convert_to<double>(); + std::cout << x << " "; + mp_t result = boost::math::erfc_inv(x); + std::cout << result << std::endl; + return boost::math::make_tuple(x, result); +} + + +int main(int argc, char*argv []) +{ + parameter_info<mp_t> arg1; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc >= 2) + { + if(strcmp(argv[1], "--limits") == 0) + { + asymptotic_limit(24); + asymptotic_limit(53); + asymptotic_limit(64); + asymptotic_limit(106); + asymptotic_limit(113); + return 0; + } + else if(strcmp(argv[1], "--erf_inv") == 0) + { + mp_t (*f)(mp_t); + f = boost::math::erf_inv; + std::cout << "Welcome.\n" + "This program will generate spot tests for the inverse erf function:\n"; + std::cout << "Enter the number of data points: "; + int points; + std::cin >> points; + data.insert(f, make_random_param(mp_t(-1), mp_t(1), points)); + } + else if(strcmp(argv[1], "--erfc_inv") == 0) + { + boost::math::tuple<mp_t, mp_t> (*f)(mp_t); + f = erfc_inv; + std::cout << "Welcome.\n" + "This program will generate spot tests for the inverse erfc function:\n"; + std::cout << "Enter the maximum *result* expected from erfc_inv: "; + double max_val; + std::cin >> max_val; + std::cout << "Enter the number of data points: "; + int points; + std::cin >> points; + parameter_info<mp_t> arg = make_random_param(mp_t(0), mp_t(max_val), points); + arg.type |= dummy_param; + data.insert(f, arg); + } + } + else + { + std::cout << "Welcome.\n" + "This program will generate spot tests for the erf and erfc functions:\n" + " erf(z) and erfc(z)\n\n"; + + do{ + if(0 == get_user_parameter_info(arg1, "a")) + return 1; + data.insert(erf_data_generator(), arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + } + + std::cout << "Enter name of test data file [default=erf_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "erf_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "erf_data"); + + return 0; +} + +/* Output for asymptotic limits: + +Erf asymptotic limit for 24 bit numbers is 2.8 after approximately 6 terms. +Erfc asymptotic limit for 24 bit numbers is 4.12064 after approximately 17 terms. +Erf asymptotic limit for 53 bit numbers is 4.3 after approximately 11 terms. +Erfc asymptotic limit for 53 bit numbers is 6.19035 after approximately 29 terms. +Erf asymptotic limit for 64 bit numbers is 4.8 after approximately 12 terms. +Erfc asymptotic limit for 64 bit numbers is 7.06004 after approximately 29 terms. +Erf asymptotic limit for 106 bit numbers is 6.5 after approximately 14 terms. +Erfc asymptotic limit for 106 bit numbers is 11.6626 after approximately 29 terms. +Erf asymptotic limit for 113 bit numbers is 6.8 after approximately 14 terms. +Erfc asymptotic limit for 113 bit numbers is 12.6802 after approximately 29 terms. +*/ + diff --git a/src/boost/libs/math/tools/expint_data.cpp b/src/boost/libs/math/tools/expint_data.cpp new file mode 100644 index 00000000..e34e3b54 --- /dev/null +++ b/src/boost/libs/math/tools/expint_data.cpp @@ -0,0 +1,64 @@ +// (C) Copyright John Maddock 2007. +// 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 <boost/math/special_functions/expint.hpp> +#include <boost/math/constants/constants.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; + +struct expint_data_generator +{ + mp_t operator()(mp_t a, mp_t b) + { + unsigned n = boost::math::tools::real_cast<unsigned>(a); + std::cout << n << " " << b << " "; + mp_t result = boost::math::expint(n, b); + std::cout << result << std::endl; + return result; + } +}; + + +int main() +{ + boost::math::expint(1, 0.06227754056453704833984375); + std::cout << boost::math::expint(1, mp_t(0.5)) << std::endl; + + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the expint function:\n" + " expint(a, b)\n\n"; + + bool cont; + std::string line; + + do{ + get_user_parameter_info(arg1, "a"); + get_user_parameter_info(arg2, "b"); + data.insert(expint_data_generator(), arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=expint_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "expint_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "expint_data"); + + return 0; +} + diff --git a/src/boost/libs/math/tools/expint_i_data.cpp b/src/boost/libs/math/tools/expint_i_data.cpp new file mode 100644 index 00000000..f8b6166a --- /dev/null +++ b/src/boost/libs/math/tools/expint_i_data.cpp @@ -0,0 +1,50 @@ +// (C) Copyright John Maddock 2007. +// 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 <boost/math/special_functions/expint.hpp> +#include <boost/math/constants/constants.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; + + +int main() +{ + parameter_info<mp_t> arg1; + test_data<mp_t> data; + + mp_t (*f)(mp_t) = boost::math::expint; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the expint Ei function:\n" + " expint(a)\n\n"; + + bool cont; + std::string line; + + do{ + get_user_parameter_info(arg1, "a"); + data.insert(f, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=expinti_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "expinti_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "expinti_data"); + + return 0; +} + diff --git a/src/boost/libs/math/tools/factorial_tables.cpp b/src/boost/libs/math/tools/factorial_tables.cpp new file mode 100644 index 00000000..2a1382df --- /dev/null +++ b/src/boost/libs/math/tools/factorial_tables.cpp @@ -0,0 +1,41 @@ +// (C) Copyright John Maddock 2007. +// 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 <boost/limits.hpp> +#include <vector> +#include "mp_t.hpp" + +void write_table(unsigned max_exponent) +{ + mp_t max = ldexp(mp_t(1), (int)max_exponent); + + std::vector<mp_t> factorials; + factorials.push_back(1); + + mp_t f(1); + unsigned i = 1; + + while(f < max) + { + factorials.push_back(f); + ++i; + f *= i; + } + + // + // now write out the results to cout: + // + std::cout << std::scientific << std::setprecision(40); + std::cout << " static const boost::array<T, " << factorials.size() << "> factorials = {\n"; + for(unsigned j = 0; j < factorials.size(); ++j) + std::cout << " " << factorials[j] << "L,\n"; + std::cout << " };\n\n"; +} + + +int main() +{ + write_table(16384/*std::numeric_limits<float>::max_exponent*/); +} diff --git a/src/boost/libs/math/tools/gamma_P_inva_data.cpp b/src/boost/libs/math/tools/gamma_P_inva_data.cpp new file mode 100644 index 00000000..3136e59b --- /dev/null +++ b/src/boost/libs/math/tools/gamma_P_inva_data.cpp @@ -0,0 +1,69 @@ +// (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 <boost/math/special_functions/gamma.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; + +// +// Force trunctation to float precision of input values: +// we must ensure that the input values are exactly representable +// in whatever type we are testing, or the output values will all +// be thrown off: +// +float external_f; +float force_truncate(const float* f) +{ + external_f = *f; + return external_f; +} + +float truncate_to_float(mp_t r) +{ + float f = boost::math::tools::real_cast<float>(r); + return force_truncate(&f); +} + +struct gamma_inverse_generator_a +{ + boost::math::tuple<mp_t, mp_t> operator()(const mp_t x, const mp_t p) + { + mp_t x1 = boost::math::gamma_p_inva(x, p); + mp_t x2 = boost::math::gamma_q_inva(x, p); + std::cout << "Inverse for " << x << " " << p << std::endl; + return boost::math::make_tuple(x1, x2); + } +}; + + +int main(int argc, char*argv []) +{ + bool cont; + std::string line; + + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the inverse incomplete gamma function:\n" + " gamma_p_inva(a, p) and gamma_q_inva(a, q)\n\n"; + + arg1 = make_power_param<mp_t>(mp_t(0), -4, 24); + arg2 = make_random_param<mp_t>(mp_t(0), mp_t(1), 15); + data.insert(gamma_inverse_generator_a(), arg1, arg2); + + line = "igamma_inva_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "igamma_inva_data"); + + return 0; +} + diff --git a/src/boost/libs/math/tools/gauss_kronrod_constants.cpp b/src/boost/libs/math/tools/gauss_kronrod_constants.cpp new file mode 100644 index 00000000..73fee4c1 --- /dev/null +++ b/src/boost/libs/math/tools/gauss_kronrod_constants.cpp @@ -0,0 +1,158 @@ +// Copyright (c) 2017 John Maddock +// 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 <boost/math/quadrature/gauss_kronrod.hpp> +#include <boost/multiprecision/cpp_bin_float.hpp> + +template <class T> +void print_gauss_constants(const char* suffix, int prec, int tag) +{ + auto ab = T::abscissa(); + auto w = T::weights(); + std::cout << std::setprecision(prec) << std::scientific; + std::size_t order = (ab[0] == 0) ? (ab.size() * 2) - 1 : ab.size() * 2; + std::cout << + "template <class T>\n" + "class gauss_detail<T, " << order << ", " << tag << ">\n" + " {\n" + " public:\n" + " static " << (prec > 40 ? " " : "constexpr ") << "std::array<T, " << ab.size() << "> const & abscissa()\n" + " {\n" + " static " << (prec > 40 ? " " : "constexpr ") << "std::array<T, " << ab.size() << "> data = {\n"; + for (unsigned i = 0; i < ab.size(); ++i) + std::cout << " " << (prec > 40 ? "BOOST_MATH_HUGE_CONSTANT(T, 0, " : "") << ab[i] << (prec > 40 ? ")" : suffix) << ",\n"; + std::cout << + "};\n" + " return data;\n" + " }\n" + " static " << (prec > 40 ? " " : "constexpr ") << "std::array<T, " << w.size() << "> const & weights()\n" + " {\n" + " static " << (prec > 40 ? " " : "constexpr ") << "std::array<T, " << w.size() << "> data = {\n"; + for (unsigned i = 0; i < w.size(); ++i) + std::cout << " " << (prec > 40 ? "BOOST_MATH_HUGE_CONSTANT(T, 0, " : "") << w[i] << (prec > 40 ? ")" : suffix) << ",\n"; + + std::cout << " };\n" + " return data;\n" + " }\n" + " };\n\n"; +} + +template <class T> +void print_gauss_kronrod_constants(const char* suffix, int prec, int tag) +{ + auto ab = T::abscissa(); + auto w = T::weights(); + std::cout << std::setprecision(prec) << std::scientific; + std::size_t order = (ab.size() * 2) - 1; + std::cout << + " template <class T>\n" + " class gauss_kronrod_detail<T, " << order << ", " << tag << ">\n" + " {\n" + " public:\n" + " static " << (prec > 40 ? " " : "constexpr ") << "std::array<T, " << ab.size() << "> const & abscissa()\n" + " {\n" + " static " << (prec > 40 ? " " : "constexpr ") << "std::array<T, " << ab.size() << "> data = {\n"; + + for (unsigned i = 0; i < ab.size(); ++i) + std::cout << " " << (prec > 40 ? "BOOST_MATH_HUGE_CONSTANT(T, 0, " : "") << ab[i] << (prec > 40 ? ")" : suffix) << ",\n"; + + std::cout << " };\n" + " return data;\n" + " }\n" + " static " << (prec > 40 ? " " : "constexpr ") << "std::array<T, " << w.size() << "> const & weights()\n" + " {\n" + " static " << (prec > 40 ? " " : "constexpr ") << "std::array<T, " << w.size() << "> data = {\n"; + + for (unsigned i = 0; i < w.size(); ++i) + std::cout << " " << (prec > 40 ? "BOOST_MATH_HUGE_CONSTANT(T, 0, " : "") << w[i] << (prec > 40 ? ")" : suffix) << ",\n"; + + std::cout << " };\n" + " return data;\n" + " }\n" + " };\n\n"; +} + + + +int main() +{ + typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<250> > mp_type; + + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 7> >("f", 9, 0); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 7> >("", 17, 1); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 7> >("L", 35, 2); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 7> >("Q", 35, 3); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 7> >("", 115, 4); + + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 10> >("f", 9, 0); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 10> >("", 17, 1); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 10> >("L", 35, 2); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 10> >("Q", 35, 3); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 10> >("", 115, 4); + + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 15> >("f", 9, 0); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 15> >("", 17, 1); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 15> >("L", 35, 2); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 15> >("Q", 35, 3); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 15> >("", 115, 4); + + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 20> >("f", 9, 0); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 20> >("", 17, 1); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 20> >("L", 35, 2); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 20> >("Q", 35, 3); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 20> >("", 115, 4); + + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 25> >("f", 9, 0); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 25> >("", 17, 1); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 25> >("L", 35, 2); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 25> >("Q", 35, 3); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 25> >("", 115, 4); + + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 30> >("f", 9, 0); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 30> >("", 17, 1); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 30> >("L", 35, 2); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 30> >("Q", 35, 3); + print_gauss_constants<boost::math::quadrature::gauss<mp_type, 30> >("", 115, 4); + + + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 15> >("f", 9, 0); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 15> >("", 17, 1); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 15> >("L", 35, 2); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 15> >("Q", 35, 3); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 15> >("", 115, 4); + + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 21> >("f", 9, 0); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 21> >("", 17, 1); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 21> >("L", 35, 2); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 21> >("Q", 35, 3); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 21> >("", 115, 4); + + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 31> >("f", 9, 0); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 31> >("", 17, 1); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 31> >("L", 35, 2); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 31> >("Q", 35, 3); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 31> >("", 115, 4); + + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 41> >("f", 9, 0); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 41> >("", 17, 1); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 41> >("L", 35, 2); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 41> >("Q", 35, 3); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 41> >("", 115, 4); + + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 51> >("f", 9, 0); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 51> >("", 17, 1); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 51> >("L", 35, 2); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 51> >("Q", 35, 3); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 51> >("", 115, 4); + + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 61> >("f", 9, 0); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 61> >("", 17, 1); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 61> >("L", 35, 2); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 61> >("Q", 35, 3); + print_gauss_kronrod_constants<boost::math::quadrature::gauss_kronrod<mp_type, 61> >("", 115, 4); + + return 0; +} + diff --git a/src/boost/libs/math/tools/generate_rational_code.cpp b/src/boost/libs/math/tools/generate_rational_code.cpp new file mode 100644 index 00000000..4f4d62a0 --- /dev/null +++ b/src/boost/libs/math/tools/generate_rational_code.cpp @@ -0,0 +1,738 @@ +// (C) Copyright John Maddock 2007. +// 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 <iostream> +#include <iomanip> +#include <fstream> +#include <string> +#include <sstream> + +int max_order = 20; +const char* path_prefix = "..\\..\\..\\boost\\math\\tools\\detail\\polynomial_"; +const char* path_prefix2 = "..\\..\\..\\boost\\math\\tools\\detail\\rational_"; + +const char* copyright_string = +"// (C) Copyright John Maddock 2007.\n" +"// Use, modification and distribution are subject to the\n" +"// Boost Software License, Version 1.0. (See accompanying file\n" +"// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" +"//\n" +"// This file is machine generated, do not edit by hand\n\n"; + + +void print_polynomials(int max_order) +{ + for(int i = 2; i <= max_order; ++i) + { + std::stringstream filename; + filename << path_prefix << "horner1_" << i << ".hpp"; + std::ofstream ofs(filename.str().c_str()); + if(ofs.bad()) + break; + // + // Output the boilerplate at the top of the header: + // + ofs << copyright_string << + "// Polynomial evaluation using Horners rule\n" + "#ifndef BOOST_MATH_TOOLS_POLY_EVAL_" << i << "_HPP\n" + "#define BOOST_MATH_TOOLS_POLY_EVAL_" << i << "_HPP\n\n" + "namespace boost{ namespace math{ namespace tools{ namespace detail{\n\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)\n" + "{\n" + " return static_cast<V>(0);\n" + "}\n" + "\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<1>*)\n" + "{\n" + " return static_cast<V>(a[0]);\n" + "}\n\n"; + + for(int order = 2; order <= i; ++order) + { + ofs << + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V& x, const mpl::int_<" << order << ">*)\n" + "{\n" + " return static_cast<V>("; + + for(int bracket = 2; bracket < order; ++bracket) + ofs << "("; + ofs << "a[" << order - 1 << "] * x + a[" << order - 2 << "]" ; + for(int item = order - 3; item >= 0; --item) + { + ofs << ") * x + a[" << item << "]"; + } + + ofs << ");\n" + "}\n\n"; + } + // + // And finally the boilerplate at the end of the header: + // + ofs << "\n}}}} // namespaces\n\n#endif // include guard\n\n"; + + filename.str(""); + filename << path_prefix << "horner2_" << i << ".hpp"; + ofs.close(); + ofs.open(filename.str().c_str()); + if(ofs.bad()) + break; + // + // Output the boilerplate at the top of the header: + // + ofs << copyright_string << + "// Polynomial evaluation using second order Horners rule\n" + "#ifndef BOOST_MATH_TOOLS_POLY_EVAL_" << i << "_HPP\n" + "#define BOOST_MATH_TOOLS_POLY_EVAL_" << i << "_HPP\n\n" + "namespace boost{ namespace math{ namespace tools{ namespace detail{\n\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)\n" + "{\n" + " return static_cast<V>(0);\n" + "}\n" + "\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<1>*)\n" + "{\n" + " return static_cast<V>(a[0]);\n" + "}\n\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V& x, const mpl::int_<2>*)\n" + "{\n" + " return static_cast<V>(a[1] * x + a[0]);\n" + "}\n\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V& x, const mpl::int_<3>*)\n" + "{\n" + " return static_cast<V>((a[2] * x + a[1]) * x + a[0]);\n" + "}\n\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V& x, const mpl::int_<4>*)\n" + "{\n" + " return static_cast<V>(((a[3] * x + a[2]) * x + a[1]) * x + a[0]);\n" + "}\n\n"; + + for(int order = 5; order <= i; ++order) + { + ofs << + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V& x, const mpl::int_<" << order << ">*)\n" + "{\n" + " V x2 = x * x;\n" + " return static_cast<V>("; + + if(order & 1) + { + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "a[" << order - 1 << "] * x2 + a[" << order - 3 << "]" ; + for(int item = order - 5; item >= 0; item -= 2) + { + ofs << ") * x2 + a[" << item << "]"; + } + ofs << " + "; + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "a[" << order - 2 << "] * x2 + a[" << order - 4 << "]" ; + for(int item = order - 6; item >= 0; item -= 2) + { + ofs << ") * x2 + a[" << item << "]"; + } + ofs << ") * x"; + } + else + { + for(int bracket = 0; bracket < (order - 1) / 2; ++bracket) + ofs << "("; + ofs << "a[" << order - 1 << "] * x2 + a[" << order - 3 << "]" ; + for(int item = order - 5; item >= 0; item -= 2) + { + ofs << ") * x2 + a[" << item << "]"; + } + ofs << ") * x + "; + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "a[" << order - 2 << "] * x2 + a[" << order - 4 << "]" ; + for(int item = order - 6; item >= 0; item -= 2) + { + ofs << ") * x2 + a[" << item << "]"; + } + } + ofs << ");\n" + "}\n\n"; + } + // + // And finally the boilerplate at the end of the header: + // + ofs << "\n}}}} // namespaces\n\n#endif // include guard\n\n"; + + + filename.str(""); + filename << path_prefix << "horner3_" << i << ".hpp"; + ofs.close(); + ofs.open(filename.str().c_str()); + if(ofs.bad()) + break; + // + // Output the boilerplate at the top of the header: + // + ofs << copyright_string << + "// Unrolled polynomial evaluation using second order Horners rule\n" + "#ifndef BOOST_MATH_TOOLS_POLY_EVAL_" << i << "_HPP\n" + "#define BOOST_MATH_TOOLS_POLY_EVAL_" << i << "_HPP\n\n" + "namespace boost{ namespace math{ namespace tools{ namespace detail{\n\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)\n" + "{\n" + " return static_cast<V>(0);\n" + "}\n" + "\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<1>*)\n" + "{\n" + " return static_cast<V>(a[0]);\n" + "}\n\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V& x, const mpl::int_<2>*)\n" + "{\n" + " return static_cast<V>(a[1] * x + a[0]);\n" + "}\n\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V& x, const mpl::int_<3>*)\n" + "{\n" + " return static_cast<V>((a[2] * x + a[1]) * x + a[0]);\n" + "}\n\n" + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V& x, const mpl::int_<4>*)\n" + "{\n" + " return static_cast<V>(((a[3] * x + a[2]) * x + a[1]) * x + a[0]);\n" + "}\n\n"; + + for(int order = 5; order <= i; ++order) + { + ofs << + "template <class T, class V>\n" + "inline V evaluate_polynomial_c_imp(const T* a, const V& x, const mpl::int_<" << order << ">*)\n" + "{\n" + " V x2 = x * x;\n" + " V t[2];\n"; + + if(order & 1) + { + ofs << " t[0] = static_cast<V>(a[" << order - 1 << "] * x2 + a[" << order - 3 << "]);\n" ; + ofs << " t[1] = static_cast<V>(a[" << order - 2 << "] * x2 + a[" << order - 4 << "]);\n" ; + for(int item = order - 5; item >= 0; item -= 2) + { + ofs << " t[0] *= x2;\n"; + if(item - 1 >= 0) + ofs << " t[1] *= x2;\n"; + ofs << " t[0] += static_cast<V>(a[" << item << "]);\n"; + if(item - 1 >= 0) + ofs << " t[1] += static_cast<V>(a[" << item - 1 << "]);\n"; + } + ofs << + " t[1] *= x;\n" + " return t[0] + t[1];\n"; + } + else + { + ofs << " t[0] = a[" << order - 1 << "] * x2 + a[" << order - 3 << "];\n" ; + ofs << " t[1] = a[" << order - 2 << "] * x2 + a[" << order - 4 << "];\n" ; + for(int item = order - 5; item >= 0; item -= 2) + { + ofs << " t[0] *= x2;\n"; + if(item - 1 >= 0) + ofs << " t[1] *= x2;\n"; + ofs << " t[0] += static_cast<V>(a[" << item << "]);\n"; + if(item - 1 >= 0) + ofs << " t[1] += static_cast<V>(a[" << item - 1 << "]);\n"; + } + ofs << " t[0] *= x;\n"; + ofs << " return t[0] + t[1];\n"; + } + ofs << "}\n\n"; + } + // + // And finally the boilerplate at the end of the header: + // + ofs << "\n}}}} // namespaces\n\n#endif // include guard\n\n"; + } +} + +void print_rationals(int max_order) +{ + for(int i = 2; i <= max_order; ++i) + { + std::stringstream filename; + filename << path_prefix2 << "horner1_" << i << ".hpp"; + std::ofstream ofs(filename.str().c_str()); + if(ofs.bad()) + break; + // + // Output the boilerplate at the top of the header: + // + ofs << copyright_string << + "// Polynomial evaluation using Horners rule\n" + "#ifndef BOOST_MATH_TOOLS_POLY_RAT_" << i << "_HPP\n" + "#define BOOST_MATH_TOOLS_POLY_RAT_" << i << "_HPP\n\n" + "namespace boost{ namespace math{ namespace tools{ namespace detail{\n\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)\n" + "{\n" + " return static_cast<V>(0);\n" + "}\n" + "\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<1>*)\n" + "{\n" + " return static_cast<V>(a[0]) / static_cast<V>(b[0]);\n" + "}\n\n"; + + for(int order = 2; order <= i; ++order) + { + ofs << + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const mpl::int_<" << order << ">*)\n" + "{\n" + " if(x <= 1)\n" + " return static_cast<V>(("; + + for(int bracket = 2; bracket < order; ++bracket) + ofs << "("; + ofs << "a[" << order - 1 << "] * x + a[" << order - 2 << "]" ; + for(int item = order - 3; item >= 0; --item) + { + ofs << ") * x + a[" << item << "]"; + } + + ofs << ") / ("; + for(int bracket = 2; bracket < order; ++bracket) + ofs << "("; + ofs << "b[" << order - 1 << "] * x + b[" << order - 2 << "]" ; + for(int item = order - 3; item >= 0; --item) + { + ofs << ") * x + b[" << item << "]"; + } + + ofs << "));\n else\n {\n V z = 1 / x;\n return static_cast<V>(("; + + for(int bracket = order - 1; bracket > 1; --bracket) + ofs << "("; + ofs << "a[" << 0 << "] * z + a[" << 1 << "]" ; + for(int item = 2; item <= order - 1; ++item) + { + ofs << ") * z + a[" << item << "]"; + } + + ofs << ") / ("; + for(int bracket = 2; bracket < order; ++bracket) + ofs << "("; + ofs << "b[" << 0 << "] * z + b[" << 1 << "]" ; + for(int item = 2; item <= order - 1; ++item) + { + ofs << ") * z + b[" << item << "]"; + } + + ofs << "));\n }\n"; + + ofs << "}\n\n"; + } + // + // And finally the boilerplate at the end of the header: + // + ofs << "\n}}}} // namespaces\n\n#endif // include guard\n\n"; + + filename.str(""); + filename << path_prefix2 << "horner2_" << i << ".hpp"; + ofs.close(); + ofs.open(filename.str().c_str()); + if(ofs.bad()) + break; + // + // Output the boilerplate at the top of the header: + // + ofs << copyright_string << + "// Polynomial evaluation using second order Horners rule\n" + "#ifndef BOOST_MATH_TOOLS_RAT_EVAL_" << i << "_HPP\n" + "#define BOOST_MATH_TOOLS_RAT_EVAL_" << i << "_HPP\n\n" + "namespace boost{ namespace math{ namespace tools{ namespace detail{\n\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)\n" + "{\n" + " return static_cast<V>(0);\n" + "}\n" + "\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<1>*)\n" + "{\n" + " return static_cast<V>(a[0]) / static_cast<V>(b[0]);\n" + "}\n\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const mpl::int_<2>*)\n" + "{\n" + " return static_cast<V>((a[1] * x + a[0]) / (b[1] * x + b[0]));\n" + "}\n\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const mpl::int_<3>*)\n" + "{\n" + " return static_cast<V>(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0]));\n" + "}\n\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const mpl::int_<4>*)\n" + "{\n" + " return static_cast<V>((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0]));\n" + "}\n\n"; + + for(int order = 5; order <= i; ++order) + { + ofs << + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const mpl::int_<" << order << ">*)\n" + "{\n" + " if(x <= 1)\n {\n" + " V x2 = x * x;\n" + " return static_cast<V>(("; + + if(order & 1) + { + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "a[" << order - 1 << "] * x2 + a[" << order - 3 << "]" ; + for(int item = order - 5; item >= 0; item -= 2) + { + ofs << ") * x2 + a[" << item << "]"; + } + ofs << " + "; + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "a[" << order - 2 << "] * x2 + a[" << order - 4 << "]" ; + for(int item = order - 6; item >= 0; item -= 2) + { + ofs << ") * x2 + a[" << item << "]"; + } + ofs << ") * x"; + } + else + { + for(int bracket = 0; bracket < (order - 1) / 2; ++bracket) + ofs << "("; + ofs << "a[" << order - 1 << "] * x2 + a[" << order - 3 << "]" ; + for(int item = order - 5; item >= 0; item -= 2) + { + ofs << ") * x2 + a[" << item << "]"; + } + ofs << ") * x + "; + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "a[" << order - 2 << "] * x2 + a[" << order - 4 << "]" ; + for(int item = order - 6; item >= 0; item -= 2) + { + ofs << ") * x2 + a[" << item << "]"; + } + } + ofs << ") / ("; + if(order & 1) + { + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "b[" << order - 1 << "] * x2 + b[" << order - 3 << "]" ; + for(int item = order - 5; item >= 0; item -= 2) + { + ofs << ") * x2 + b[" << item << "]"; + } + ofs << " + "; + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "b[" << order - 2 << "] * x2 + b[" << order - 4 << "]" ; + for(int item = order - 6; item >= 0; item -= 2) + { + ofs << ") * x2 + b[" << item << "]"; + } + ofs << ") * x"; + } + else + { + for(int bracket = 0; bracket < (order - 1) / 2; ++bracket) + ofs << "("; + ofs << "b[" << order - 1 << "] * x2 + b[" << order - 3 << "]" ; + for(int item = order - 5; item >= 0; item -= 2) + { + ofs << ") * x2 + b[" << item << "]"; + } + ofs << ") * x + "; + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "b[" << order - 2 << "] * x2 + b[" << order - 4 << "]" ; + for(int item = order - 6; item >= 0; item -= 2) + { + ofs << ") * x2 + b[" << item << "]"; + } + } + + ofs << "));\n }\n else\n {\n V z = 1 / x;\n V z2 = 1 / (x * x);\n return static_cast<V>(("; + + if(order & 1) + { + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "a[" << 0 << "] * z2 + a[" << 2 << "]" ; + for(int item = 4; item < order; item += 2) + { + ofs << ") * z2 + a[" << item << "]"; + } + ofs << " + "; + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "a[" << 1 << "] * z2 + a[" << 3 << "]" ; + for(int item = 5; item < order; item += 2) + { + ofs << ") * z2 + a[" << item << "]"; + } + ofs << ") * z"; + } + else + { + for(int bracket = 0; bracket < (order - 1) / 2; ++bracket) + ofs << "("; + ofs << "a[" << 0 << "] * z2 + a[" << 2 << "]" ; + for(int item = 4; item < order; item += 2) + { + ofs << ") * z2 + a[" << item << "]"; + } + ofs << ") * z + "; + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "a[" << 1 << "] * z2 + a[" << 3 << "]" ; + for(int item = 5; item < order; item += 2) + { + ofs << ") * z2 + a[" << item << "]"; + } + } + + ofs << ") / ("; + + if(order & 1) + { + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "b[" << 0 << "] * z2 + b[" << 2 << "]" ; + for(int item = 4; item < order; item += 2) + { + ofs << ") * z2 + b[" << item << "]"; + } + ofs << " + "; + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "b[" << 1 << "] * z2 + b[" << 3 << "]" ; + for(int item = 5; item < order; item += 2) + { + ofs << ") * z2 + b[" << item << "]"; + } + ofs << ") * z"; + } + else + { + for(int bracket = 0; bracket < (order - 1) / 2; ++bracket) + ofs << "("; + ofs << "b[" << 0 << "] * z2 + b[" << 2 << "]" ; + for(int item = 4; item < order; item += 2) + { + ofs << ") * z2 + b[" << item << "]"; + } + ofs << ") * z + "; + for(int bracket = 0; bracket < (order - 1) / 2 - 1; ++bracket) + ofs << "("; + ofs << "b[" << 1 << "] * z2 + b[" << 3 << "]" ; + for(int item = 5; item < order; item += 2) + { + ofs << ") * z2 + b[" << item << "]"; + } + } + ofs << "));\n }\n"; + + ofs << "}\n\n"; + } + // + // And finally the boilerplate at the end of the header: + // + ofs << "\n}}}} // namespaces\n\n#endif // include guard\n\n"; + + + filename.str(""); + filename << path_prefix2 << "horner3_" << i << ".hpp"; + ofs.close(); + ofs.open(filename.str().c_str()); + if(ofs.bad()) + break; + // + // Output the boilerplate at the top of the header: + // + ofs << copyright_string << + "// Polynomial evaluation using second order Horners rule\n" + "#ifndef BOOST_MATH_TOOLS_RAT_EVAL_" << i << "_HPP\n" + "#define BOOST_MATH_TOOLS_RAT_EVAL_" << i << "_HPP\n\n" + "namespace boost{ namespace math{ namespace tools{ namespace detail{\n\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)\n" + "{\n" + " return static_cast<V>(0);\n" + "}\n" + "\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<1>*)\n" + "{\n" + " return static_cast<V>(a[0]) / static_cast<V>(b[0]);\n" + "}\n\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const mpl::int_<2>*)\n" + "{\n" + " return static_cast<V>((a[1] * x + a[0]) / (b[1] * x + b[0]));\n" + "}\n\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const mpl::int_<3>*)\n" + "{\n" + " return static_cast<V>(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0]));\n" + "}\n\n" + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const mpl::int_<4>*)\n" + "{\n" + " return static_cast<V>((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0]));\n" + "}\n\n"; + + for(int order = 5; order <= i; ++order) + { + ofs << + "template <class T, class U, class V>\n" + "inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const mpl::int_<" << order << ">*)\n" + "{\n" + " if(x <= 1)\n {\n" + " V x2 = x * x;\n" + " V t[4];\n"; + + if(order & 1) + { + ofs << " t[0] = a[" << order - 1 << "] * x2 + a[" << order - 3 << "];\n" ; + ofs << " t[1] = a[" << order - 2 << "] * x2 + a[" << order - 4 << "];\n" ; + ofs << " t[2] = b[" << order - 1 << "] * x2 + b[" << order - 3 << "];\n" ; + ofs << " t[3] = b[" << order - 2 << "] * x2 + b[" << order - 4 << "];\n" ; + for(int item = order - 5; item >= 0; item -= 2) + { + ofs << " t[0] *= x2;\n"; + if(item - 1 >= 0) + ofs << " t[1] *= x2;\n"; + ofs << " t[2] *= x2;\n"; + if(item - 1 >= 0) + ofs << " t[3] *= x2;\n"; + ofs << " t[0] += static_cast<V>(a[" << item << "]);\n"; + if(item - 1 >= 0) + ofs << " t[1] += static_cast<V>(a[" << item - 1 << "]);\n"; + ofs << " t[2] += static_cast<V>(b[" << item << "]);\n"; + if(item - 1 >= 0) + ofs << " t[3] += static_cast<V>(b[" << item - 1 << "]);\n"; + } + ofs << " t[1] *= x;\n"; + ofs << " t[3] *= x;\n"; + } + else + { + ofs << " t[0] = a[" << order - 1 << "] * x2 + a[" << order - 3 << "];\n" ; + ofs << " t[1] = a[" << order - 2 << "] * x2 + a[" << order - 4 << "];\n" ; + ofs << " t[2] = b[" << order - 1 << "] * x2 + b[" << order - 3 << "];\n" ; + ofs << " t[3] = b[" << order - 2 << "] * x2 + b[" << order - 4 << "];\n" ; + for(int item = order - 5; item >= 0; item -= 2) + { + ofs << " t[0] *= x2;\n"; + if(item - 1 >= 0) + ofs << " t[1] *= x2;\n"; + ofs << " t[2] *= x2;\n"; + if(item - 1 >= 0) + ofs << " t[3] *= x2;\n"; + ofs << " t[0] += static_cast<V>(a[" << item << "]);\n"; + if(item - 1 >= 0) + ofs << " t[1] += static_cast<V>(a[" << item - 1 << "]);\n"; + ofs << " t[2] += static_cast<V>(b[" << item << "]);\n"; + if(item - 1 >= 0) + ofs << " t[3] += static_cast<V>(b[" << item - 1 << "]);\n"; + } + ofs << " t[0] *= x;\n"; + ofs << " t[2] *= x;\n"; + } + ofs << " return (t[0] + t[1]) / (t[2] + t[3]);\n"; + + ofs << " }\n else\n {\n V z = 1 / x;\n V z2 = 1 / (x * x);\n V t[4];\n"; + + if(order & 1) + { + ofs << " t[0] = a[" << 0 << "] * z2 + a[" << 2 << "];\n" ; + ofs << " t[1] = a[" << 1 << "] * z2 + a[" << 3 << "];\n" ; + ofs << " t[2] = b[" << 0 << "] * z2 + b[" << 2 << "];\n" ; + ofs << " t[3] = b[" << 1 << "] * z2 + b[" << 3 << "];\n" ; + for(int item = 4; item < order; item += 2) + { + ofs << " t[0] *= z2;\n"; + if(item + 1 < order) + ofs << " t[1] *= z2;\n"; + ofs << " t[2] *= z2;\n"; + if(item + 1 < order) + ofs << " t[3] *= z2;\n"; + ofs << " t[0] += static_cast<V>(a[" << item << "]);\n"; + if(item + 1 < order) + ofs << " t[1] += static_cast<V>(a[" << item + 1 << "]);\n"; + ofs << " t[2] += static_cast<V>(b[" << item << "]);\n"; + if(item + 1 < order) + ofs << " t[3] += static_cast<V>(b[" << item + 1 << "]);\n"; + } + ofs << " t[1] *= z;\n"; + ofs << " t[3] *= z;\n"; + } + else + { + ofs << " t[0] = a[" << 0 << "] * z2 + a[" << 2 << "];\n" ; + ofs << " t[1] = a[" << 1 << "] * z2 + a[" << 3 << "];\n" ; + ofs << " t[2] = b[" << 0 << "] * z2 + b[" << 2 << "];\n" ; + ofs << " t[3] = b[" << 1 << "] * z2 + b[" << 3 << "];\n" ; + for(int item = 4; item < order; item += 2) + { + ofs << " t[0] *= z2;\n"; + if(item + 1 < order) + ofs << " t[1] *= z2;\n"; + ofs << " t[2] *= z2;\n"; + if(item + 1 < order) + ofs << " t[3] *= z2;\n"; + ofs << " t[0] += static_cast<V>(a[" << item << "]);\n"; + if(item + 1 < order) + ofs << " t[1] += static_cast<V>(a[" << item + 1 << "]);\n"; + ofs << " t[2] += static_cast<V>(b[" << item << "]);\n"; + if(item + 1 < order) + ofs << " t[3] += static_cast<V>(b[" << item + 1 << "]);\n"; + } + ofs << " t[0] *= z;\n"; + ofs << " t[2] *= z;\n"; + } + ofs << " return (t[0] + t[1]) / (t[2] + t[3]);\n }\n"; + + ofs << "}\n\n"; + } + // + // And finally the boilerplate at the end of the header: + // + ofs << "\n}}}} // namespaces\n\n#endif // include guard\n\n"; + } +} + +int main() +{ + for(int i = 2; i <= max_order; ++i) + { + print_polynomials(i); + print_rationals(i); + } + return 0; +} + + + diff --git a/src/boost/libs/math/tools/generate_rational_test.cpp b/src/boost/libs/math/tools/generate_rational_test.cpp new file mode 100644 index 00000000..7093906d --- /dev/null +++ b/src/boost/libs/math/tools/generate_rational_test.cpp @@ -0,0 +1,524 @@ +// (C) Copyright John Maddock 2007. +// 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) + +#define BOOST_MATH_POLY_METHOD 0 +#define BOOST_MATH_RATIONAL_METHOD 0 + +#include <boost/random.hpp> +#include <boost/math/tools/rational.hpp> +#include <iostream> +#include <fstream> +#include "mp_t.hpp" + +int main() +{ + using namespace boost::math; + using namespace boost::math::tools; + + static const unsigned max_order = 20; + std::cout << std::scientific << std::setprecision(40); + + boost::mt19937 rnd; + boost::variate_generator< + boost::mt19937, + boost::uniform_int<> > gen(rnd, boost::uniform_int<>(1, 12)); + + for(unsigned i = 1; i < max_order; ++i) + { + std::vector<int> coef; + for(unsigned j = 0; j < i; ++j) + { + coef.push_back(gen()); + } + std::cout << std::scientific; + std::cout << +" //\n" +" // Polynomials of order " << i-1 << "\n" +" //\n" +" static const U n" << i << "c[" << i << "] = { "; + for(unsigned j = 0; j < i; ++j) + { + if(j) + std::cout << ", "; + std::cout << coef[j]; + } + std::cout << " };\n"; + std::cout << + " static const boost::array<U, " << i << "> n" << i << "a = { "; + for(unsigned j = 0; j < i; ++j) + { + if(j) + std::cout << ", "; + std::cout << coef[j]; + } + std::cout << " };\n"; + + mp_t r1 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.125), i); + mp_t r2 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.25), i); + mp_t r3 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.75), i); + mp_t r4 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(1) - mp_t(1) / 64, i); + mp_t r5 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(6.5), i); + mp_t r6 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(10247.25), i); + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.125), " << i << "),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.25), " << i << "),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.75), " << i << "),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f), " << i << "),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n"; + if(fabs(r5) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(6.5), " << i << "),\n" + " static_cast<T>(" << r5 << "L),\n" + " tolerance);\n"; + if(fabs(r6) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(10247.25), " << i << "),\n" + " static_cast<T>(" << r6 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n"; + if(fabs(r5) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(6.5)),\n" + " static_cast<T>(" << r5 << "L),\n" + " tolerance);\n"; + if(fabs(r6) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(10247.25)),\n" + " static_cast<T>(" << r6 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "a, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "a, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "a, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "a, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n"; + if(fabs(r5) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "a, static_cast<T>(6.5)),\n" + " static_cast<T>(" << r5 << "L),\n" + " tolerance);\n"; + if(fabs(r6) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "a, static_cast<T>(10247.25)),\n" + " static_cast<T>(" << r6 << "L),\n" + " tolerance);\n\n"; + + r1 = boost::math::tools::evaluate_even_polynomial(&coef[0], mp_t(0.125), i); + r2 = boost::math::tools::evaluate_even_polynomial(&coef[0], mp_t(0.25), i); + r3 = boost::math::tools::evaluate_even_polynomial(&coef[0], mp_t(0.75), i); + r4 = boost::math::tools::evaluate_even_polynomial(&coef[0], mp_t(1) - mp_t(1) / 64, i); + r5 = boost::math::tools::evaluate_even_polynomial(&coef[0], mp_t(6.5), i); + r6 = boost::math::tools::evaluate_even_polynomial(&coef[0], mp_t(10247.25), i); + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.125), " << i << "),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.25), " << i << "),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.75), " << i << "),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f), " << i << "),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n"; + if(fabs(r5) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(6.5f), " << i << "),\n" + " static_cast<T>(" << r5 << "L),\n" + " tolerance);\n"; + if(fabs(r6) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(10247.25f), " << i << "),\n" + " static_cast<T>(" << r6 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n"; + if(fabs(r5) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(6.5f)),\n" + " static_cast<T>(" << r5 << "L),\n" + " tolerance);\n"; + if(fabs(r6) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(10247.25f)),\n" + " static_cast<T>(" << r6 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "a, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "a, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "a, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "a, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n"; + if(fabs(r5) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "a, static_cast<T>(6.5f)),\n" + " static_cast<T>(" << r5 << "L),\n" + " tolerance);\n"; + if(fabs(r6) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "a, static_cast<T>(10247.25f)),\n" + " static_cast<T>(" << r6 << "L),\n" + " tolerance);\n\n"; + + if(i > 1) + { + r1 = boost::math::tools::evaluate_odd_polynomial(&coef[0], mp_t(0.125), i); + r2 = boost::math::tools::evaluate_odd_polynomial(&coef[0], mp_t(0.25), i); + r3 = boost::math::tools::evaluate_odd_polynomial(&coef[0], mp_t(0.75), i); + r4 = boost::math::tools::evaluate_odd_polynomial(&coef[0], mp_t(1) - mp_t(1) / 64, i); + r5 = boost::math::tools::evaluate_odd_polynomial(&coef[0], mp_t(6.5), i); + r6 = boost::math::tools::evaluate_odd_polynomial(&coef[0], mp_t(10247.25), i); + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.125), " << i << "),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.25), " << i << "),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.75), " << i << "),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f), " << i << "),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n"; + if(fabs(r5) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(6.5f), " << i << "),\n" + " static_cast<T>(" << r5 << "L),\n" + " tolerance);\n"; + if(fabs(r6) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(10247.25f), " << i << "),\n" + " static_cast<T>(" << r6 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n"; + if(fabs(r5) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(6.5f)),\n" + " static_cast<T>(" << r5 << "L),\n" + " tolerance);\n"; + if(fabs(r6) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(10247.25f)),\n" + " static_cast<T>(" << r6 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "a, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "a, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "a, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "a, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n"; + if(fabs(r5) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "a, static_cast<T>(6.5f)),\n" + " static_cast<T>(" << r5 << "L),\n" + " tolerance);\n"; + if(fabs(r6) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "a, static_cast<T>(10247.25f)),\n" + " static_cast<T>(" << r6 << "L),\n" + " tolerance);\n\n"; + } + + r1 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.125), i); + r2 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.25), i); + r3 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.75), i); + r4 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(1) - mp_t(1) / 64, i); + r5 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(6.5), i); + r6 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(10247.25), i); + + coef.clear(); + for(unsigned j = 0; j < i; ++j) + { + coef.push_back(gen()); + } + std::cout << +" //\n" +" // Rational functions of order " << i-1 << "\n" +" //\n" +" static const U d" << i << "c[" << i << "] = { "; + for(unsigned j = 0; j < i; ++j) + { + if(j) + std::cout << ", "; + std::cout << coef[j]; + } + std::cout << " };\n"; + std::cout << + " static const boost::array<U, " << i << "> d" << i << "a = { "; + for(unsigned j = 0; j < i; ++j) + { + if(j) + std::cout << ", "; + std::cout << coef[j]; + } + std::cout << " };\n"; + + mp_t r1d = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.125), i); + mp_t r2d = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.25), i); + mp_t r3d = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.75), i); + mp_t r4d = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(1) - mp_t(1) / 64, i); + mp_t r5d = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(6.5), i); + mp_t r6d = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(10247.25), i); + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.125), " << i << "),\n" + " static_cast<T>(" << r1/r1d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.25), " << i << "),\n" + " static_cast<T>(" << r2/r2d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.75), " << i << "),\n" + " static_cast<T>(" << r3/r3d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f), " << i << "),\n" + " static_cast<T>(" << r4/r4d << "L),\n" + " tolerance);\n"; + if(fabs(r5/r5d) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(6.5f), " << i << "),\n" + " static_cast<T>(" << r5/r5d << "L),\n" + " tolerance);\n"; + if(fabs(r6/r6d) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(10247.25f), " << i << "),\n" + " static_cast<T>(" << r6/r6d << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1/r1d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2/r2d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3/r3d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4/r4d << "L),\n" + " tolerance);\n"; + if(fabs(r5/r5d) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(6.5f)),\n" + " static_cast<T>(" << r5/r5d << "L),\n" + " tolerance);\n"; + if(fabs(r6/r6d) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(10247.25f)),\n" + " static_cast<T>(" << r6/r6d << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "a, d" << i << "a, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1/r1d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "a, d" << i << "a, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2/r2d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "a, d" << i << "a, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3/r3d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "a, d" << i << "a, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4/r4d << "L),\n" + " tolerance);\n"; + if(fabs(r5/r5d) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "a, d" << i << "a, static_cast<T>(6.5f)),\n" + " static_cast<T>(" << r5/r5d << "L),\n" + " tolerance);\n"; + if(fabs(r6/r6d) < tools::max_value<float>()) + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "a, d" << i << "a, static_cast<T>(10247.25f)),\n" + " static_cast<T>(" << r6/r6d << "L),\n" + " tolerance);\n\n"; + } + + return 0; +} + + + diff --git a/src/boost/libs/math/tools/generate_test_values.cpp b/src/boost/libs/math/tools/generate_test_values.cpp new file mode 100644 index 00000000..5c7c247f --- /dev/null +++ b/src/boost/libs/math/tools/generate_test_values.cpp @@ -0,0 +1,41 @@ +// (C) Copyright John Maddock 2005. +// 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) + +#ifndef NTL_STD_CXX +# define NTL_STD_CXX +#endif + +#include <iostream> +#include <iomanip> +#include "mp_t.hpp" + +mp_t log1p(mp_t arg) +{ + return log(arg + 1); +} + +mp_t expm1(mp_t arg) +{ + return exp(arg) - 1; +} + +int main() +{ + mp_t r, root_two; + r = 1.0; + root_two = 2.0; + root_two = sqrt(root_two); + r /= root_two; + mp_t lim = pow(mp_t(2), mp_t(-128)); + std::cout << std::scientific << std::setprecision(40); + while(r > lim) + { + std::cout << " { " << r << "L, " << log1p(r) << "L, " << expm1(r) << "L, }, \n"; + std::cout << " { " << -r << "L, " << log1p(-r) << "L, " << expm1(-r) << "L, }, \n"; + r /= root_two; + } + return 0; +} + diff --git a/src/boost/libs/math/tools/hermite_data.cpp b/src/boost/libs/math/tools/hermite_data.cpp new file mode 100644 index 00000000..156a7254 --- /dev/null +++ b/src/boost/libs/math/tools/hermite_data.cpp @@ -0,0 +1,67 @@ +// (C) Copyright John Maddock 2007. +// 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 <boost/math/tools/test_data.hpp> +#include <boost/math/special_functions/hermite.hpp> +#include <fstream> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + + +template<class T> +boost::math::tuple<T, T, T> hermite_data(T n, T x) +{ + n = floor(n); + T r1 = hermite(boost::math::tools::real_cast<unsigned>(n), x); + return boost::math::make_tuple(n, x, r1); +} + +int main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + std::cout << boost::math::hermite(10, static_cast<mp_t>(1e300)) << std::endl; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + if(0 == get_user_parameter_info(arg1, "n")) + return 1; + if(0 == get_user_parameter_info(arg2, "x")) + return 1; + arg1.type |= dummy_param; + arg2.type |= dummy_param; + + data.insert(&hermite_data<mp_t>, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=hermite.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "hermite.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + diff --git a/src/boost/libs/math/tools/heuman_lambda_data.cpp b/src/boost/libs/math/tools/heuman_lambda_data.cpp new file mode 100644 index 00000000..44aa3803 --- /dev/null +++ b/src/boost/libs/math/tools/heuman_lambda_data.cpp @@ -0,0 +1,67 @@ +// 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 <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <boost/math/special_functions/ellint_1.hpp> +#include <boost/math/special_functions/jacobi_zeta.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +mp_t heuman_lambda(mp_t phi, mp_t k) +{ + mp_t kp = sqrt(1 - k *k); + if((k * k < tools::epsilon<float>()) && (fabs(phi) >= constants::half_pi<mp_t>())) + throw std::domain_error(""); + return ellint_1(kp, phi) / ellint_1(kp) + ellint_1(k) * jacobi_zeta(kp, phi) / constants::half_pi<mp_t>(); +} + +int cpp_main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + if(0 == get_user_parameter_info(arg1, "phi")) + return 1; + if(0 == get_user_parameter_info(arg2, "k")) + return 1; + + mp_t(*fp)(mp_t, mp_t) = &heuman_lambda; + data.insert(fp, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=heuman_lambda_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "heuman_lambda_data.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/hyp_0f2_data.cpp b/src/boost/libs/math/tools/hyp_0f2_data.cpp new file mode 100644 index 00000000..6bdaedb2 --- /dev/null +++ b/src/boost/libs/math/tools/hyp_0f2_data.cpp @@ -0,0 +1,113 @@ +// (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) + +#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 10000000 + +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <map> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +struct hypergeometric_0f2_gen +{ + mp_t operator()(mp_t b1, mp_t b2, mp_t z) + { + mp_t result = 0; + mp_t abs_result = 0; + mp_t term = 1; + mp_t k = 0; + + do + { + result += term; + abs_result += fabs(term); + if (fabs(result) * boost::math::tools::epsilon<mp_t>() > fabs(term)) + break; + ++k; + term /= b1++; + term /= b2++; + term /= k; + term *= z; + } while (true); + // + // check precision: + // + if (abs_result * boost::math::tools::epsilon<mp_t>() / fabs(result) > 1e-40) + throw std::domain_error("Unable to calculate result"); + + std::cout << b1 << " " << b2 << " " << z << " " << result << std::endl; + return result; + } +}; + +int main(int, char* []) +{ + parameter_info<mp_t> arg1, arg2, arg3, arg4; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for 2F0:\n"; + + std::string line; + bool cont = true; + + while (cont) + { + float range; + std::cout << "Enter the range to calculate over for b1 and b2 (single value, range will be -x to x): "; + std::cin >> range; + + float z_range; + std::cout << "Enter the range to calculate over for z (single value, range will be -x to x): "; + std::cin >> z_range; + + int num_spots; + std::cout << "Enter how many test points to calculate: "; + std::cin >> num_spots; + + std::vector<mp_t> v; + random_ns::mt19937 rnd; + random_ns::uniform_real_distribution<float> ur_a(-range, range); + random_ns::uniform_real_distribution<float> ur_z(-z_range, z_range); + + do + { + mp_t b1 = ur_a(rnd); + mp_t b2 = ur_a(rnd); + mp_t z = ur_z(rnd); + + arg1 = make_single_param(b1); + arg2 = make_single_param(b2); + arg3 = make_single_param(z); + data.insert(hypergeometric_0f2_gen(), arg1, arg2, arg3); + } while (num_spots--); + + std::cout << "Any more data?"; + std::cin >> cont; + + } + + + + std::cout << "Enter name of test data file [default=hypergeometric_0f2.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "hypergeometric_0f2.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/hyp_1f1_big_data.cpp b/src/boost/libs/math/tools/hyp_1f1_big_data.cpp new file mode 100644 index 00000000..4bef9d2f --- /dev/null +++ b/src/boost/libs/math/tools/hyp_1f1_big_data.cpp @@ -0,0 +1,179 @@ +// (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) + +#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 10000000 + +#include <boost/math/special_functions/hypergeometric_1f1.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <map> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#define BOOST_MATH_USE_MPFR +#include "mp_t.hpp" + +#include <boost/multiprecision/mpfi.hpp> + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; +using namespace boost::multiprecision; + +typedef mpfi_float_1000 mpfi_type; + +mp_t hypergeometric_1f1_generic_series(mp_t a_, mp_t b_, mp_t z_) +{ + using namespace boost::math::tools; + using namespace boost::math; + using namespace std; + using namespace boost::multiprecision; + + mpfi_type a(a_), b(b_), z(z_), sum(0), term(1), diff, term0(0); + unsigned n = 0; + bool cont = true; + + unsigned max_n; + if (b < 0) + max_n = itrunc(-b) + 10000; + else + max_n = 10000000; + + mpfi_type overflow_limit("1.189731495357231765e+4900"); // a bit less than LDBL_MAX for extended long doubles. + + do + { + sum += term; + term *= (((a + n) / ((b + n) * (n + 1))) * z); + ++n; + diff = fabs(term / sum); + if (n > max_n) + { + std::cout << "Aborting series evaluation due to too many iterations...\n"; + throw evaluation_error(""); + } + if (fabs(upper(sum)) > overflow_limit) + { + std::cout << "Aborting series evaluation due to over large sum...\n"; + throw evaluation_error(""); + } + cont = (fabs(upper(diff)) > 1e-40) || (b + n < 0) || (fabs(term0) < fabs(term)); + term0 = term; + //std::cout << upper(term) << " " << upper(sum) << " " << upper(diff) << " " << cont << std::endl; + } while (cont); + + mp_t r = mp_t(width(sum) / median(sum)); + if (fabs(r) > 1e-40) + { + std::cout << "Aborting to to error in result of " << r << std::endl; + throw evaluation_error(""); + } + std::cout << "Found error in sum was " << r << std::endl; + + return mp_t(median(sum)); +} + + +struct hypergeometric_1f1_gen +{ + mp_t operator()(mp_t a1, mp_t a2, mp_t z) + { + mp_t result; + try { + result = hypergeometric_1f1_generic_series(a1, a2, z); + std::cout << a1 << " " << a2 << " " << z << " " << result << std::endl; + } + catch (...) + { + throw std::domain_error(""); + } + if (fabs(result) > (std::numeric_limits<double>::max)()) + { + std::cout << "Rejecting over large value\n"; + throw std::domain_error(""); + } + return result; + } +}; + + +int main(int, char* []) +{ + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for 1F1 (Yeh!!):\n"; + + std::string line; + //bool cont; + + std::vector<mp_t> v; + random_ns::mt19937 rnd; + random_ns::uniform_real_distribution<float> ur_a(0, 1); + + mp_t p = ur_a(rnd); + p *= 1e6; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e5; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e4; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e3; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e2; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-5; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-12; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-30; + v.push_back(p); + v.push_back(-p); + + for (unsigned i = 0; i < v.size(); ++i) + { + for (unsigned j = 0; j < v.size(); ++j) + { + for (unsigned k = 0; k < v.size(); ++k) + { + std::cout << i << " " << j << " " << k << std::endl; + std::cout << v[i] << " " << (v[j] * 3) / 2 << " " << (v[j] * 5) / 4 << std::endl; + arg1 = make_single_param(v[i]); + arg2 = make_single_param(mp_t((v[j] * 3) / 2)); + arg3 = make_single_param(mp_t((v[k] * 5) / 4)); + data.insert(hypergeometric_1f1_gen(), arg1, arg2, arg3); + } + } + } + + + std::cout << "Enter name of test data file [default=hypergeometric_1f1.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "hypergeometric_1f1.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/hyp_1f1_data.cpp b/src/boost/libs/math/tools/hyp_1f1_data.cpp new file mode 100644 index 00000000..0205b42b --- /dev/null +++ b/src/boost/libs/math/tools/hyp_1f1_data.cpp @@ -0,0 +1,143 @@ +// (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) + +#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 10000000 + +#include <boost/math/special_functions/hypergeometric_1f1.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <map> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +struct hypergeometric_1f1_gen +{ + mp_t operator()(mp_t a1, mp_t a2, mp_t z) + { + std::cout << a1 << " " << a2 << " " << z << std::endl; + mp_t result = boost::math::detail::hypergeometric_1f1_generic_series(a1, a2, z, boost::math::policies::policy<>()); + std::cout << a1 << " " << a2 << " " << z << " " << result << std::endl; + return result; + } +}; + +struct hypergeometric_1f1_gen_2 +{ + mp_t operator()(mp_t a1, mp_t a2, mp_t z) + { + mp_t result = boost::math::detail::hypergeometric_1f1_generic_series(a1, a2, z, boost::math::policies::policy<>()); + std::cout << a1 << " " << a2 << " " << z << " " << result << std::endl; + if (fabs(result) > (std::numeric_limits<double>::max)()) + { + std::cout << "Discarding result as too large\n"; + throw std::domain_error(""); + } + if (static_cast<double>(result) == 1) + { + std::cout << "Discarding result as unity\n"; + throw std::domain_error(""); // uninteresting result. + } + return result; + } +}; + + +int main(int, char* []) +{ + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for 2F0:\n"; + + std::string line; + bool cont; + +#if 1 + std::vector<mp_t> v; + random_ns::mt19937 rnd; + random_ns::uniform_real_distribution<float> ur_a(0, 1); + + mp_t p = ur_a(rnd); + p *= 1e6; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e5; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e4; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e3; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e2; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-5; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-12; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-30; + v.push_back(p); + v.push_back(-p); + + for (unsigned i = 0; i < v.size(); ++i) + { + for (unsigned j = 0; j < v.size(); ++j) + { + for (unsigned k = 0; k < v.size(); ++k) + { + arg1 = make_single_param(v[i]); + arg2 = make_single_param(v[j] * 3 / 2); + arg3 = make_single_param(v[k] * 5 / 4); + data.insert(hypergeometric_1f1_gen_2(), arg1, arg2, arg3); + } + } + } + + +#else + + do { + get_user_parameter_info(arg1, "a1"); + get_user_parameter_info(arg2, "a2"); + get_user_parameter_info(arg3, "z"); + data.insert(hypergeometric_1f1_gen(), arg1, arg2, arg3); + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + } while (cont); + +#endif + std::cout << "Enter name of test data file [default=hypergeometric_1f1.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "hypergeometric_1f1.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/hyp_1f1_log_big_data.cpp b/src/boost/libs/math/tools/hyp_1f1_log_big_data.cpp new file mode 100644 index 00000000..ab8b09e4 --- /dev/null +++ b/src/boost/libs/math/tools/hyp_1f1_log_big_data.cpp @@ -0,0 +1,132 @@ +// (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) + +#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 10000000 + +#include <boost/math/special_functions/hypergeometric_1f1.hpp> +#include <boost/math/special_functions/hypergeometric_pfq.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <map> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#define BOOST_MATH_USE_MPFR +#include "mp_t.hpp" + +#include <boost/multiprecision/mpfr.hpp> + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; +using namespace boost::multiprecision; + + +struct hypergeometric_1f1_gen +{ + mp_t operator()(mp_t a1, mp_t a2, mp_t z) + { + mp_t result; + try { + result = (mp_t)log(abs(boost::math::hypergeometric_pFq_precision({ mpfr_float(a1) }, { mpfr_float(a2) }, mpfr_float(z), 70, 25.0))); + std::cout << a1 << " " << a2 << " " << z << " " << result << std::endl; + } + catch (...) + { + throw std::domain_error(""); + } + if (fabs(result) > (std::numeric_limits<double>::max)()) + { + std::cout << "Rejecting over large value\n"; + throw std::domain_error(""); + } + if (fabs(result) < 1/1024.0) + { + std::cout << "Rejecting over small value\n"; + throw std::domain_error(""); + } + return result; + } +}; + + +int main(int, char* []) +{ + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for 1F1 (Yeh!!):\n"; + + std::string line; + //bool cont; + + std::vector<mp_t> v; + random_ns::mt19937 rnd; + random_ns::uniform_real_distribution<float> ur_a(0, 1); + + mp_t p = ur_a(rnd); + p *= 1e6; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e5; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e4; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e3; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e2; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-5; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-12; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-30; + v.push_back(p); + v.push_back(-p); + + for (unsigned i = 0; i < v.size(); ++i) + { + for (unsigned j = 0; j < v.size(); ++j) + { + for (unsigned k = 0; k < v.size(); ++k) + { + std::cout << i << " " << j << " " << k << std::endl; + std::cout << v[i] << " " << (v[j] * 3) / 2 << " " << (v[k] * 5) / 4 << std::endl; + arg1 = make_single_param(v[i]); + arg2 = make_single_param(mp_t((v[j] * 3) / 2)); + arg3 = make_single_param(mp_t((v[k] * 5) / 4)); + data.insert(hypergeometric_1f1_gen(), arg1, arg2, arg3); + } + } + } + + + std::cout << "Enter name of test data file [default=hypergeometric_1f1.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "hypergeometric_1f1.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/hyp_1f1_reg_big_data.cpp b/src/boost/libs/math/tools/hyp_1f1_reg_big_data.cpp new file mode 100644 index 00000000..6989547e --- /dev/null +++ b/src/boost/libs/math/tools/hyp_1f1_reg_big_data.cpp @@ -0,0 +1,127 @@ +// (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) + +#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 10000000 + +#include <boost/math/special_functions/hypergeometric_1f1.hpp> +#include <boost/math/special_functions/hypergeometric_pfq.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <map> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#define BOOST_MATH_USE_MPFR +#include "mp_t.hpp" + +#include <boost/multiprecision/mpfr.hpp> + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; +using namespace boost::multiprecision; + + +struct hypergeometric_1f1_gen +{ + mp_t operator()(mp_t a1, mp_t a2, mp_t z) + { + mp_t result; + try { + result = (mp_t)boost::math::hypergeometric_pFq_precision({ mpfr_float(a1) }, { mpfr_float(mpfr_float(a2)) }, mpfr_float(z), 50, 25.0) / boost::multiprecision::tgamma(a2); + std::cout << a1 << " " << a2 << " " << z << " " << result << std::endl; + } + catch (...) + { + throw std::domain_error(""); + } + if (fabs(result) > (std::numeric_limits<double>::max)()) + { + std::cout << "Rejecting over large value\n"; + throw std::domain_error(""); + } + return result; + } +}; + + +int main(int, char* []) +{ + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for 1F1 (Yeh!!):\n"; + + std::string line; + //bool cont; + + std::vector<mp_t> v; + random_ns::mt19937 rnd; + random_ns::uniform_real_distribution<float> ur_a(0, 1); + + mp_t p = ur_a(rnd); + p *= 1e6; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e5; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e4; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e3; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e2; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-5; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-12; + v.push_back(p); + v.push_back(-p); + p = ur_a(rnd); + p *= 1e-30; + v.push_back(p); + v.push_back(-p); + + for (unsigned i = 0; i < v.size(); ++i) + { + for (unsigned j = 0; j < v.size(); ++j) + { + for (unsigned k = 0; k < v.size(); ++k) + { + std::cout << i << " " << j << " " << k << std::endl; + std::cout << v[i] << " " << (v[j] * 3) / 2 << " " << (v[j] * 5) / 4 << std::endl; + arg1 = make_single_param(v[i]); + arg2 = make_single_param(mp_t((v[j] * 3) / 2)); + arg3 = make_single_param(mp_t((v[k] * 5) / 4)); + data.insert(hypergeometric_1f1_gen(), arg1, arg2, arg3); + } + } + } + + + std::cout << "Enter name of test data file [default=hypergeometric_1f1.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "hypergeometric_1f1.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/hyp_1f2_data.cpp b/src/boost/libs/math/tools/hyp_1f2_data.cpp new file mode 100644 index 00000000..c3ebee3d --- /dev/null +++ b/src/boost/libs/math/tools/hyp_1f2_data.cpp @@ -0,0 +1,116 @@ +// (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) + +#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 10000000 + +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <map> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +struct hypergeometric_1f2_gen +{ + mp_t operator()(mp_t a1, mp_t b1, mp_t b2, mp_t z) + { + mp_t result = 0; + mp_t abs_result = 0; + mp_t term = 1; + mp_t k = 0; + + do + { + result += term; + abs_result += fabs(term); + if (fabs(result) * boost::math::tools::epsilon<mp_t>() > fabs(term)) + break; + ++k; + term *= a1++; + term /= b1++; + term /= b2++; + term /= k; + term *= z; + } while (true); + // + // check precision: + // + if (abs_result * boost::math::tools::epsilon<mp_t>() / fabs(result) > 1e-40) + throw std::domain_error("Unable to calculate result"); + + std::cout << a1 << " " << b1 << " " << b2 << " " << z << " " << result << std::endl; + return result; + } +}; + +int main(int, char* []) +{ + parameter_info<mp_t> arg1, arg2, arg3, arg4; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for 2F0:\n"; + + std::string line; + bool cont = true; + + while (cont) + { + float range; + std::cout << "Enter the range to calculate over for a1, b1 and b2 (single value, range will be -x to x): "; + std::cin >> range; + + float z_range; + std::cout << "Enter the range to calculate over for z (single value, range will be -x to x): "; + std::cin >> z_range; + + int num_spots; + std::cout << "Enter how many test points to calculate: "; + std::cin >> num_spots; + + std::vector<mp_t> v; + random_ns::mt19937 rnd; + random_ns::uniform_real_distribution<float> ur_a(-range, range); + random_ns::uniform_real_distribution<float> ur_z(-z_range, z_range); + + do + { + mp_t a1 = ur_a(rnd); + mp_t b1 = ur_a(rnd); + mp_t b2 = ur_a(rnd); + mp_t z = ur_z(rnd); + + arg1 = make_single_param(a1); + arg2 = make_single_param(b1); + arg3 = make_single_param(b2); + arg4 = make_single_param(z); + data.insert(hypergeometric_1f2_gen(), arg1, arg2, arg3, arg4); + } while (num_spots--); + + std::cout << "Any more data?"; + std::cin >> cont; + + } + + + + std::cout << "Enter name of test data file [default=hypergeometric_1f2.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "hypergeometric_1f2.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/hyp_2f0_data.cpp b/src/boost/libs/math/tools/hyp_2f0_data.cpp new file mode 100644 index 00000000..a750dff5 --- /dev/null +++ b/src/boost/libs/math/tools/hyp_2f0_data.cpp @@ -0,0 +1,85 @@ +// (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 <boost/math/special_functions/hypergeometric_2f0.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <map> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +struct hypergeometric_2f0_gen +{ + mp_t operator()(mp_t a1, mp_t a2, mp_t z) + { + std::cout << a1 << " " << a2 << " " << z << std::endl; + mp_t result = boost::math::detail::hypergeometric_2f0_generic_series(a1, a2, z, boost::math::policies::policy<>()); + std::cout << a1 << " " << a2 << " " << z << " " << result << std::endl; + return result; + } +}; + +struct hypergeometric_2f0_gen_spec1 +{ + boost::math::tuple<mp_t, mp_t, mp_t, mp_t> operator()(mp_t a1, mp_t z) + { + mp_t result = boost::math::detail::hypergeometric_2f0_generic_series(a1, a1 + 0.5, z, boost::math::policies::policy<>()); + std::cout << a1 << " " << a1 + 0.5 << " " << z << " " << result << std::endl; + return boost::math::make_tuple(a1, a1 + 0.5, z, result); + } +}; + +int main(int, char* []) +{ + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for 2F0:\n"; + + std::string line; + bool cont; + +#if 1 + arg1 = make_periodic_param(mp_t(-20), mp_t(-1), 19); + arg2 = make_random_param(mp_t(-5), mp_t(5), 8); + arg1.type |= dummy_param; + arg2.type |= dummy_param; + data.insert(hypergeometric_2f0_gen_spec1(), arg1, arg2); + + +#else + + do { + get_user_parameter_info(arg1, "a1"); + get_user_parameter_info(arg2, "a2"); + get_user_parameter_info(arg3, "z"); + data.insert(hypergeometric_2f0_gen(), arg1, arg2, arg3); + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + } while (cont); + +#endif + std::cout << "Enter name of test data file [default=hypergeometric_2f0.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "hypergeometric_2f0.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/hyp_2f1_data.cpp b/src/boost/libs/math/tools/hyp_2f1_data.cpp new file mode 100644 index 00000000..c742e743 --- /dev/null +++ b/src/boost/libs/math/tools/hyp_2f1_data.cpp @@ -0,0 +1,100 @@ +// (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) + +#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 10000000 + +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <map> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +struct hypergeometric_2f1_gen +{ + mp_t operator()(mp_t a1, mp_t a2, mp_t b, mp_t z) + { + mp_t result = 0; + mp_t abs_result = 0; + mp_t term = 1; + mp_t k = 0; + + do + { + result += term; + abs_result += fabs(term); + if (fabs(result) * boost::math::tools::epsilon<mp_t>() > fabs(term)) + break; + ++k; + term *= a1++; + term *= a2++; + term /= b++; + term /= k; + term *= z; + } while (true); + // + // check precision: + // + if (abs_result * boost::math::tools::epsilon<mp_t>() / fabs(result) > 1e-40) + throw std::domain_error("Unable to calculate result"); + + std::cout << a1 << " " << a2 << " " << b << " " << z << " " << result << std::endl; + return result; + } +}; + +int main(int, char* []) +{ + parameter_info<mp_t> arg1, arg2, arg3, arg4; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for 2F0:\n"; + + std::string line; + bool cont; + + std::vector<mp_t> v; + random_ns::mt19937 rnd; + random_ns::uniform_real_distribution<float> ur_a(-100, 100); + random_ns::uniform_real_distribution<float> ur_z(-1, 1); + + int num_spots; + std::cout << "Enter how many test points to calculate: "; + std::cin >> num_spots; + + do + { + mp_t a1 = ur_a(rnd); + mp_t a2 = ur_a(rnd); + mp_t b = ur_a(rnd); + mp_t z = ur_z(rnd); + + arg1 = make_single_param(a1); + arg2 = make_single_param(a2); + arg3 = make_single_param(b); + arg4 = make_single_param(z); + data.insert(hypergeometric_2f1_gen(), arg1, arg2, arg3, arg4); + } while (num_spots--); + + + std::cout << "Enter name of test data file [default=hypergeometric_2f1.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "hypergeometric_2f1.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/hyp_2f2_data.cpp b/src/boost/libs/math/tools/hyp_2f2_data.cpp new file mode 100644 index 00000000..378db1cd --- /dev/null +++ b/src/boost/libs/math/tools/hyp_2f2_data.cpp @@ -0,0 +1,121 @@ +// (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) + +#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 10000000 + +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <map> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +struct hypergeometric_2f2_gen +{ + mp_t operator()(mp_t a1, mp_t a2, mp_t b1, mp_t b2, mp_t z) + { + mp_t result = 0; + mp_t abs_result = 0; + mp_t term = 1; + mp_t k = 0; + + do + { + result += term; + abs_result += fabs(term); + if (fabs(result) * boost::math::tools::epsilon<mp_t>() > fabs(term)) + break; + ++k; + term *= a1++; + term *= a2++; + term /= b1++; + term /= b2++; + term /= k; + term *= z; + } while (true); + // + // check precision: + // + if (abs_result * boost::math::tools::epsilon<mp_t>() / fabs(result) > 1e-40) + throw std::domain_error("Unable to calculate result"); + if(fabs(result) > (std::numeric_limits<double>::max)()) + throw std::domain_error("Unable to calculate result"); + + std::cout << a1 << " " << a2 << " " << b1 << " " << b2 << " " << z << " " << result << std::endl; + return result; + } +}; + +int main(int, char* []) +{ + parameter_info<mp_t> arg1, arg2, arg3, arg4, arg5; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for 2F2:\n"; + + std::string line; + bool cont = true; + + while (cont) + { + float range; + std::cout << "Enter the range to calculate over for a1, a2, b1 and b2 (single value, range will be -x to x): "; + std::cin >> range; + + float z_range; + std::cout << "Enter the range to calculate over for z (single value, range will be -x to x): "; + std::cin >> z_range; + + int num_spots; + std::cout << "Enter how many test points to calculate: "; + std::cin >> num_spots; + + std::vector<mp_t> v; + random_ns::mt19937 rnd; + random_ns::uniform_real_distribution<float> ur_a(-range, range); + random_ns::uniform_real_distribution<float> ur_z(-z_range, z_range); + + do + { + mp_t a1 = ur_a(rnd); + mp_t a2 = ur_a(rnd); + mp_t b1 = ur_a(rnd); + mp_t b2 = ur_a(rnd); + mp_t z = ur_z(rnd); + + arg1 = make_single_param(a1); + arg2 = make_single_param(a2); + arg3 = make_single_param(b1); + arg4 = make_single_param(b2); + arg5 = make_single_param(z); + data.insert(hypergeometric_2f2_gen(), arg1, arg2, arg3, arg4, arg5); + } while (num_spots--); + + std::cout << "Any more data?"; + std::cin >> cont; + + } + + + + std::cout << "Enter name of test data file [default=hypergeometric_2f2.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "hypergeometric_2f2.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/hypergeometric_1F1_error_plot.cpp b/src/boost/libs/math/tools/hypergeometric_1F1_error_plot.cpp new file mode 100644 index 00000000..c9c1410b --- /dev/null +++ b/src/boost/libs/math/tools/hypergeometric_1F1_error_plot.cpp @@ -0,0 +1,224 @@ +// 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) + +#define BOOST_ENABLE_ASSERT_HANDLER +#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY INT_MAX +// for consistent behaviour across compilers/platforms: +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false +// overflow to infinity is OK, we treat these as zero error as long as the sign is correct! +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#include <iostream> +#include <ctime> +#include <boost/multiprecision/mpfr.hpp> +#include <boost/math/special_functions/hypergeometric_1F1.hpp> +#include <boost/math/special_functions/hypergeometric_pFq.hpp> +#include <boost/math/special_functions/relative_difference.hpp> + +#include <boost/random.hpp> +#include <set> +#include <fstream> +#include <boost/iostreams/tee.hpp> +#include <boost/iostreams/stream.hpp> + +typedef double test_type; +using boost::multiprecision::mpfr_float; + +namespace boost { + // + // We convert assertions into exceptions, so we can log them and continue: + // + void assertion_failed(char const * expr, char const *, char const * file, long line) + { + std::ostringstream oss; + oss << file << ":" << line << " Assertion failed: " << expr; + throw std::runtime_error(oss.str()); + } + +} + +void print_value(double x, std::ostream& os = std::cout) +{ + int e; + double m = std::frexp(x, &e); + m = std::ldexp(m, 54); + e -= 54; + boost::int64_t val = (boost::int64_t)m; + BOOST_ASSERT(std::ldexp((double)val, e) == x); + os << "std::ldexp((double)" << val << ", " << e << ")"; +} + + +void print_row(double a, double b, double z, mpfr_float result, std::ostream& os = std::cout) +{ + os << " {{ "; + print_value(a, os); + os << ", "; + print_value(b, os); + os << ", "; + print_value(z, os); + os << ", SC_(" << std::setprecision(45) << result << ") }}" << std::endl; +} + +struct error_data +{ + error_data(double a, double b, double z, boost::intmax_t e) + : a(a), b(b), z(z), error(e) {} + double a, b, z; + boost::intmax_t error; + bool operator<(const error_data& other)const + { + return error < other.error; + } +}; + +int main() +{ + try { + test_type max_a, max_b, max_z, min_a, min_b, min_z; + + unsigned number_of_samples; + + std::ofstream log_stream, incalculable_stream, unevaluated_stream, bins_stream; + std::string basename; + + std::cout << "Enter range for a: "; + std::cin >> min_a >> max_a; + std::cout << "Enter range for b: "; + std::cin >> min_b >> max_b; + std::cout << "Enter range for z: "; + std::cin >> min_z >> max_z; + std::cout << "Enter number of samples: "; + std::cin >> number_of_samples; + std::cout << "Enter basename for log files: "; + std::cin >> basename; + + typedef boost::iostreams::tee_device<std::ostream, std::ostream> tee_sink; + typedef boost::iostreams::stream<tee_sink> tee_stream; + + log_stream.open((basename + ".log").c_str()); + tee_stream tee_log(tee_sink(std::cout, log_stream)); + incalculable_stream.open((basename + "_incalculable.log").c_str()); + unevaluated_stream.open((basename + "_unevaluated.log").c_str()); + bins_stream.open((basename + "_bins.csv").c_str()); + tee_stream tee_bins(tee_sink(std::cout, bins_stream)); + + boost::random::mt19937 gen(std::time(0)); + boost::random::uniform_real_distribution<test_type> a_dist(min_a, max_a); + boost::random::uniform_real_distribution<test_type> b_dist(min_b, max_b); + boost::random::uniform_real_distribution<test_type> z_dist(min_z, max_z); + + std::multiset<error_data> errors; + std::map<std::pair<int, int>, int> bins; + + unsigned incalculable = 0; + unsigned evaluation_errors = 0; + test_type max_error = 0; + + do + { + test_type a = a_dist(gen); + test_type b = b_dist(gen); + test_type z = z_dist(gen); + test_type found, expected; + mpfr_float mp_expected; + + try { + mp_expected = boost::math::hypergeometric_pFq_precision({ mpfr_float(a) }, { mpfr_float(b) }, mpfr_float(z), 25, 200.0); + expected = (test_type)mp_expected; + } + catch (const std::exception&) + { + // Unable to compute reference value: + ++incalculable; + tee_log << "Unable to compute reference value in reasonable time: " << std::endl; + print_row(a, b, z, mpfr_float(0), tee_log); + incalculable_stream << std::setprecision(6) << std::scientific << a << "," << b << "," << z << "\n"; + continue; + } + try + { + found = boost::math::hypergeometric_1F1(a, b, z); + } + catch (const std::exception&) + { + ++evaluation_errors; + --number_of_samples; + log_stream << "Unexpected exception calculating value: " << std::endl; + print_row(a, b, z, mp_expected, log_stream); + unevaluated_stream << std::setprecision(6) << std::scientific << a << "," << b << "," << z << "\n"; + continue; + } + test_type err = boost::math::epsilon_difference(found, expected); + if (err > max_error) + { + tee_log << "New maximum error is: " << err << std::endl; + print_row(a, b, z, mp_expected, tee_log); + max_error = err; + } + try { + errors.insert(error_data(a, b, z, boost::math::lltrunc(err))); + } + catch (...) + { + errors.insert(error_data(a, b, z, INT_MAX)); + } + --number_of_samples; + if (number_of_samples % 500 == 0) + std::cout << number_of_samples << " samples to go" << std::endl; + } while (number_of_samples); + + tee_log << "Max error found was: " << max_error << std::endl; + + unsigned current_bin = 0; + unsigned lim = 1; + unsigned old_lim = 0; + + while (errors.size()) + { + old_lim = lim; + lim *= 2; + //std::cout << "Enter upper limit for bin " << current_bin << ": "; + //std::cin >> lim; + auto p = errors.upper_bound(error_data(0, 0, 0, lim)); + int bin_count = std::distance(errors.begin(), p); + if (bin_count) + { + std::ofstream os((basename + "_errors_" + std::to_string(current_bin + 1) + ".csv").c_str()); + os << "a,b,z,error\n"; + bins[std::make_pair(old_lim, lim)] = bin_count; + for (auto pos = errors.begin(); pos != p; ++pos) + { + os << pos->a << "," << pos->b << "," << pos->z << "," << pos->error << "\n"; + } + errors.erase(errors.begin(), p); + } + ++current_bin; + } + + tee_bins << "Results:\n\n"; + tee_bins << "#bin,Range,2^N,Count\n"; + int hash = 0; + for (auto p = bins.begin(); p != bins.end(); ++p, ++hash) + { + tee_bins << hash << "," << p->first.first << "-" << p->first.second << "," << hash+1 << "," << p->second << std::endl; + } + if (evaluation_errors) + { + tee_bins << ",Failed,," << evaluation_errors << std::endl; + } + if (incalculable) + { + tee_bins << ",Incalculable,," << incalculable << std::endl; + } + } + catch (const std::exception& e) + { + std::cout << "Terminating with unhandled exception: " << e.what() << std::endl; + } + + return 0; +} + diff --git a/src/boost/libs/math/tools/hypergeometric_1F1_map_neg_b_fwd_recurrence.cpp b/src/boost/libs/math/tools/hypergeometric_1F1_map_neg_b_fwd_recurrence.cpp new file mode 100644 index 00000000..ce1fe325 --- /dev/null +++ b/src/boost/libs/math/tools/hypergeometric_1F1_map_neg_b_fwd_recurrence.cpp @@ -0,0 +1,193 @@ +// 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) + +#define BOOST_ENABLE_ASSERT_HANDLER +#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY INT_MAX +// for consistent behaviour across compilers/platforms: +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false +// overflow to infinity is OK, we treat these as zero error as long as the sign is correct! +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#include <iostream> +#include <ctime> +#include <boost/multiprecision/mpfr.hpp> +#include <boost/multiprecision/cpp_bin_float.hpp> +#include <boost/math/special_functions/hypergeometric_1F1.hpp> +#include <boost/math/special_functions/hypergeometric_pFq.hpp> +#include <boost/math/special_functions/relative_difference.hpp> + +#include <boost/random.hpp> +#include <set> +#include <fstream> +#include <boost/iostreams/tee.hpp> +#include <boost/iostreams/stream.hpp> + +using boost::multiprecision::mpfr_float; + +namespace boost { + // + // We convert assertions into exceptions, so we can log them and continue: + // + void assertion_failed(char const * expr, char const *, char const * file, long line) + { + std::ostringstream oss; + oss << file << ":" << line << " Assertion failed: " << expr; + throw std::runtime_error(oss.str()); + } + +} + +typedef boost::multiprecision::cpp_bin_float_quad test_type; + +int main() +{ + using std::floor; + using std::ceil; + try { + test_type a_start, a_end; + test_type b_start, b_end; + test_type a_mult, b_mult; + + std::cout << "Enter range for paramater a: "; + std::cin >> a_start >> a_end; + std::cout << "Enter range for paramater b: "; + std::cin >> b_start >> b_end; + std::cout << "Enter multiplier for a parameter: "; + std::cin >> a_mult; + std::cout << "Enter multiplier for b parameter: "; + std::cin >> b_mult; + + double error_limit = 200; + double time_limit = 10.0; + + for (test_type a = a_start; a < a_end; a_start < 0 ? a /= a_mult : a *= a_mult) + { + for (test_type b = b_start; b < b_end; b_start < 0 ? b /= b_mult : b *= b_mult) + { + test_type z_mult = 2; + test_type last_good = 0; + test_type bad = 0; + try { + for (test_type z = 1; z < 1e10; z *= z_mult, z_mult *= 2) + { + // std::cout << "z = " << z << std::endl; + boost::uintmax_t max_iter = 1000; + test_type calc = boost::math::tools::function_ratio_from_forwards_recurrence(boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients<test_type>(a, b, z), std::numeric_limits<test_type>::epsilon() * 2, max_iter); + test_type reference = (test_type)(boost::math::hypergeometric_pFq_precision({ mpfr_float(a) }, { mpfr_float(b) }, mpfr_float(z), 50, time_limit) / boost::math::hypergeometric_pFq_precision({ mpfr_float(a + 1) }, { mpfr_float(b + 1) }, mpfr_float(z), std::numeric_limits<test_type>::digits10 * 2, time_limit)); + double err = (double)boost::math::epsilon_difference(reference, calc); + + if (err < error_limit) + { + last_good = z; + break; + } + else + { + bad = z; + } + } + } + catch (const std::exception& e) + { + std::cout << "Unexpected exception: " << e.what() << std::endl; + std::cout << "For a = " << a << " b = " << b << " z = " << bad * z_mult / 2 << std::endl; + } + test_type z_limit; + if (0 == bad) + z_limit = 1; // Any z is large enough + else if (0 == last_good) + z_limit = std::numeric_limits<test_type > ::infinity(); + else + { + // + // At this stage last_good and bad should bracket the edge of the domain, bisect to narrow things down: + // + z_limit = last_good == 0 ? 0 : boost::math::tools::bisect([&a, b, error_limit, time_limit](test_type z) + { + boost::uintmax_t max_iter = 1000; + test_type calc = boost::math::tools::function_ratio_from_forwards_recurrence(boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients<test_type>(a, b, z), std::numeric_limits<test_type>::epsilon() * 2, max_iter); + test_type reference = (test_type)(boost::math::hypergeometric_pFq_precision({ mpfr_float(a) }, { mpfr_float(b) }, mpfr_float(z), 50, time_limit + 20) / boost::math::hypergeometric_pFq_precision({ mpfr_float(a + 1) }, { mpfr_float(b + 1) }, mpfr_float(z), std::numeric_limits<test_type>::digits10 * 2, time_limit + 20)); + test_type err = boost::math::epsilon_difference(reference, calc); + return err < error_limit ? 1 : -1; + }, bad, last_good, boost::math::tools::equal_floor()).first; + z_limit = floor(z_limit + 2); // Give ourselves some headroom! + } + // std::cout << "z_limit = " << z_limit << std::endl; + // + // Now over again for backwards recurrence domain at the same points: + // + bad = z_limit > 1e10 ? 1e10 : z_limit; + last_good = 0; + z_mult = 1.1; + for (test_type z = bad; z > 1; z /= z_mult, z_mult *= 2) + { + // std::cout << "z = " << z << std::endl; + try { + boost::uintmax_t max_iter = 1000; + test_type calc = boost::math::tools::function_ratio_from_backwards_recurrence(boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients<test_type>(a, b, z), std::numeric_limits<test_type>::epsilon() * 2, max_iter); + test_type reference = (test_type)(boost::math::hypergeometric_pFq_precision({ mpfr_float(a) }, { mpfr_float(b) }, mpfr_float(z), 50, time_limit) / boost::math::hypergeometric_pFq_precision({ mpfr_float(a - 1) }, { mpfr_float(b - 1) }, mpfr_float(z), std::numeric_limits<test_type>::digits10 * 2, time_limit)); + test_type err = boost::math::epsilon_difference(reference, calc); + + if (err < error_limit) + { + last_good = z; + break; + } + else + { + bad = z; + } + } + catch (const std::exception& e) + { + bad = z; + std::cout << "Unexpected exception: " << e.what() << std::endl; + std::cout << "For a = " << a << " b = " << b << " z = " << z << std::endl; + } + } + test_type lower_z_limit; + if (last_good < 1) + lower_z_limit = 0; + else if (last_good >= bad) + { + boost::uintmax_t max_iter = 1000; + test_type z = bad; + test_type calc = boost::math::tools::function_ratio_from_forwards_recurrence(boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients<test_type>(a, b, z), std::numeric_limits<test_type>::epsilon() * 2, max_iter); + test_type reference = (test_type)(boost::math::hypergeometric_pFq_precision({ mpfr_float(a) }, { mpfr_float(b) }, mpfr_float(z), 50, time_limit) / boost::math::hypergeometric_pFq_precision({ mpfr_float(a + 1) }, { mpfr_float(b + 1) }, mpfr_float(z), std::numeric_limits<test_type>::digits10 * 2, time_limit)); + test_type err = boost::math::epsilon_difference(reference, calc); + if (err < error_limit) + { + lower_z_limit = bad; // Both forwards and backwards iteration work!!! + } + else + throw std::runtime_error("Internal logic failed!"); + } + else + { + // + // At this stage last_good and bad should bracket the edge of the domain, bisect to narrow things down: + // + lower_z_limit = last_good == 0 ? 0 : boost::math::tools::bisect([&a, b, error_limit, time_limit](test_type z) + { + boost::uintmax_t max_iter = 1000; + test_type calc = boost::math::tools::function_ratio_from_backwards_recurrence(boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients<test_type>(a, b, z), std::numeric_limits<test_type>::epsilon() * 2, max_iter); + test_type reference = (test_type)(boost::math::hypergeometric_pFq_precision({ mpfr_float(a) }, { mpfr_float(b) }, mpfr_float(z), 50, time_limit + 20) / boost::math::hypergeometric_pFq_precision({ mpfr_float(a - 1) }, { mpfr_float(b - 1) }, mpfr_float(z), std::numeric_limits<test_type>::digits10 * 2, time_limit + 20)); + test_type err = boost::math::epsilon_difference(reference, calc); + return err < error_limit ? 1 : -1; + }, last_good, bad, boost::math::tools::equal_floor()).first; + z_limit = ceil(z_limit - 2); // Give ourselves some headroom! + } + + std::cout << std::setprecision(std::numeric_limits<test_type>::max_digits10) << "{ " << a << ", " << b << ", " << lower_z_limit << ", " << z_limit << "}," << std::endl; + } + } + } + catch (const std::exception& e) + { + std::cout << "Unexpected exception: " << e.what() << std::endl; + } + return 0; +} + diff --git a/src/boost/libs/math/tools/hypergeometric_dist_data.cpp b/src/boost/libs/math/tools/hypergeometric_dist_data.cpp new file mode 100644 index 00000000..55352f03 --- /dev/null +++ b/src/boost/libs/math/tools/hypergeometric_dist_data.cpp @@ -0,0 +1,95 @@ +// (C) Copyright John Maddock 2009. +// 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) + +//#define BOOST_MATH_INSTRUMENT + +#include <boost/math/distributions/hypergeometric.hpp> +#include <boost/math/special_functions/trunc.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/random/uniform_int.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; + +std::mt19937 rnd; + +struct hypergeometric_generator +{ + boost::math::tuple< + mp_t, + mp_t, + mp_t, + mp_t, + mp_t, + mp_t, + mp_t> operator()(mp_t rN, mp_t rr, mp_t rn) + { + using namespace std; + using namespace boost; + using namespace boost::math; + + if((rr > rN) || (rr < rn)) + throw std::domain_error(""); + + try{ + int N = itrunc(rN); + int r = itrunc(rr); + int n = itrunc(rn); + boost::uniform_int<> ui((std::max)(0, n + r - N), (std::min)(n, r)); + int k = ui(rnd); + + hypergeometric_distribution<mp_t> d(r, n, N); + + mp_t p = pdf(d, k); + if((p == 1) || (p == 0)) + { + // trivial case, don't clutter up our table with it: + throw std::domain_error(""); + } + mp_t c = cdf(d, k); + mp_t cc = cdf(complement(d, k)); + + std::cout << "N = " << N << " r = " << r << " n = " << n << " PDF = " << p << " CDF = " << c << " CCDF = " << cc << std::endl; + + return boost::math::make_tuple(r, n, N, k, p, c, cc); + } + catch(const std::exception& e) + { + std::cout << e.what() << std::endl; + throw std::domain_error(""); + } + } +}; + +int main(int argc, char*argv []) +{ + std::string line; + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests hypergeoemtric distribution:\n"; + + arg1 = make_power_param(mp_t(0), 1, 21); + arg2 = make_power_param(mp_t(0), 1, 21); + arg3 = make_power_param(mp_t(0), 1, 21); + + arg1.type |= dummy_param; + arg2.type |= dummy_param; + arg3.type |= dummy_param; + + data.insert(hypergeometric_generator(), arg1, arg2, arg3); + + line = "hypergeometric_dist_data2.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "hypergeometric_dist_data2"); + + return 0; +} + diff --git a/src/boost/libs/math/tools/ibeta_data.cpp b/src/boost/libs/math/tools/ibeta_data.cpp new file mode 100644 index 00000000..667365ec --- /dev/null +++ b/src/boost/libs/math/tools/ibeta_data.cpp @@ -0,0 +1,303 @@ +// (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 <boost/math/special_functions/gamma.hpp> +#include <boost/math/special_functions/beta.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <map> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +template <class T> +struct ibeta_fraction1_t +{ + typedef std::pair<T, T> result_type; + + ibeta_fraction1_t(T a_, T b_, T x_) : a(a_), b(b_), x(x_), k(1) {} + + result_type operator()() + { + T aN; + if(k & 1) + { + int m = (k - 1) / 2; + aN = -(a + m) * (a + b + m) * x; + aN /= a + 2*m; + aN /= a + 2*m + 1; + } + else + { + int m = k / 2; + aN = m * (b - m) *x; + aN /= a + 2*m - 1; + aN /= a + 2*m; + } + ++k; + return std::make_pair(aN, T(1)); + } + +private: + T a, b, x; + int k; +}; + +// +// This function caches previous calls to beta +// just so we can speed things up a bit: +// +template <class T> +T get_beta(T a, T b) +{ + static std::map<std::pair<T, T>, T> m; + + if(a < b) + std::swap(a, b); + + std::pair<T, T> p(a, b); + typename std::map<std::pair<T, T>, T>::const_iterator i = m.find(p); + if(i != m.end()) + return i->second; + + T r = beta(a, b); + p.first = a; + p.second = b; + m[p] = r; + + return r; +} + +// +// compute the continued fraction: +// +template <class T> +T get_ibeta_fraction1(T a, T b, T x) +{ + ibeta_fraction1_t<T> f(a, b, x); + T fract = boost::math::tools::continued_fraction_a(f, boost::math::policies::digits<T, boost::math::policies::policy<> >()); + T denom = (a * (fract + 1)); + T num = pow(x, a) * pow(1 - x, b); + if(num == 0) + return 0; + else if(denom == 0) + return -1; + return num / denom; +} +// +// calculate the incomplete beta from the fraction: +// +template <class T> +std::pair<T,T> ibeta_fraction1(T a, T b, T x) +{ + T bet = get_beta(a, b); + if(x > ((a+1)/(a+b+2))) + { + T fract = get_ibeta_fraction1(b, a, 1-x); + if(fract/bet > 0.75) + { + fract = get_ibeta_fraction1(a, b, x); + return std::make_pair(fract, bet - fract); + } + return std::make_pair(bet - fract, fract); + } + T fract = get_ibeta_fraction1(a, b, x); + if(fract/bet > 0.75) + { + fract = get_ibeta_fraction1(b, a, 1-x); + return std::make_pair(bet - fract, fract); + } + return std::make_pair(fract, bet - fract); + +} +// +// calculate the regularised incomplete beta from the fraction: +// +template <class T> +std::pair<T,T> ibeta_fraction1_regular(T a, T b, T x) +{ + T bet = get_beta(a, b); + if(x > ((a+1)/(a+b+2))) + { + T fract = get_ibeta_fraction1(b, a, 1-x); + if(fract == 0) + bet = 1; // normalise so we don't get 0/0 + else if(bet == 0) + return std::make_pair(T(-1), T(-1)); // Yikes!! + if(fract / bet > 0.75) + { + fract = get_ibeta_fraction1(a, b, x); + return std::make_pair(fract / bet, 1 - (fract / bet)); + } + return std::make_pair(1 - (fract / bet), fract / bet); + } + T fract = get_ibeta_fraction1(a, b, x); + if(fract / bet > 0.75) + { + fract = get_ibeta_fraction1(b, a, 1-x); + return std::make_pair(1 - (fract / bet), fract / bet); + } + return std::make_pair(fract / bet, 1 - (fract / bet)); +} + +// +// we absolutely must trunctate the input values to float +// precision: we have to be certain that the input values +// can be represented exactly in whatever width floating +// point type we are testing, otherwise the output will +// necessarily be off. +// +float external_f; +float force_truncate(const float* f) +{ + external_f = *f; + return external_f; +} + +float truncate_to_float(mp_t r) +{ + float f = boost::math::tools::real_cast<float>(r); + return force_truncate(&f); +} + +boost::mt19937 rnd; +boost::uniform_real<float> ur_a(1.0F, 5.0F); +boost::variate_generator<boost::mt19937, boost::uniform_real<float> > gen(rnd, ur_a); +boost::uniform_real<float> ur_a2(0.0F, 100.0F); +boost::variate_generator<boost::mt19937, boost::uniform_real<float> > gen2(rnd, ur_a2); + +struct beta_data_generator +{ + boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t, mp_t, mp_t> operator()(mp_t ap, mp_t bp, mp_t x_) + { + float a = truncate_to_float(real_cast<float>(gen() * pow(mp_t(10), ap))); + float b = truncate_to_float(real_cast<float>(gen() * pow(mp_t(10), bp))); + float x = truncate_to_float(real_cast<float>(x_)); + std::cout << a << " " << b << " " << x << std::endl; + std::pair<mp_t, mp_t> ib_full = ibeta_fraction1(mp_t(a), mp_t(b), mp_t(x)); + std::pair<mp_t, mp_t> ib_reg = ibeta_fraction1_regular(mp_t(a), mp_t(b), mp_t(x)); + return boost::math::make_tuple(a, b, x, ib_full.first, ib_full.second, ib_reg.first, ib_reg.second); + } +}; + +// medium sized values: +struct beta_data_generator_medium +{ + boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t, mp_t, mp_t> operator()(mp_t x_) + { + mp_t a = gen2(); + mp_t b = gen2(); + mp_t x = x_; + a = ConvPrec(a, 22); + b = ConvPrec(b, 22); + x = ConvPrec(x, 22); + std::cout << a << " " << b << " " << x << std::endl; + //mp_t exp_beta = boost::math::beta(a, b, x); + std::pair<mp_t, mp_t> ib_full = ibeta_fraction1(mp_t(a), mp_t(b), mp_t(x)); + /*exp_beta = boost::math::tools::relative_error(ib_full.first, exp_beta); + if(exp_beta > 1e-40) + { + std::cout << exp_beta << std::endl; + }*/ + std::pair<mp_t, mp_t> ib_reg = ibeta_fraction1_regular(mp_t(a), mp_t(b), mp_t(x)); + return boost::math::make_tuple(a, b, x, ib_full.first, ib_full.second, ib_reg.first, ib_reg.second); + } +}; + +struct beta_data_generator_small +{ + boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t, mp_t, mp_t> operator()(mp_t x_) + { + float a = truncate_to_float(gen2()/10); + float b = truncate_to_float(gen2()/10); + float x = truncate_to_float(real_cast<float>(x_)); + std::cout << a << " " << b << " " << x << std::endl; + std::pair<mp_t, mp_t> ib_full = ibeta_fraction1(mp_t(a), mp_t(b), mp_t(x)); + std::pair<mp_t, mp_t> ib_reg = ibeta_fraction1_regular(mp_t(a), mp_t(b), mp_t(x)); + return boost::math::make_tuple(a, b, x, ib_full.first, ib_full.second, ib_reg.first, ib_reg.second); + } +}; + +struct beta_data_generator_int +{ + boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t, mp_t, mp_t> operator()(mp_t a, mp_t b, mp_t x_) + { + float x = truncate_to_float(real_cast<float>(x_)); + std::cout << a << " " << b << " " << x << std::endl; + std::pair<mp_t, mp_t> ib_full = ibeta_fraction1(a, b, mp_t(x)); + std::pair<mp_t, mp_t> ib_reg = ibeta_fraction1_regular(a, b, mp_t(x)); + return boost::math::make_tuple(a, b, x, ib_full.first, ib_full.second, ib_reg.first, ib_reg.second); + } +}; + +int main(int, char* []) +{ + parameter_info<mp_t> arg1, arg2, arg3, arg4, arg5; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the incomplete beta functions:\n" + " beta(a, b, x) and ibeta(a, b, x)\n\n" + "This is not an interactive program be prepared for a long wait!!!\n\n"; + + arg1 = make_periodic_param(mp_t(-5), mp_t(6), 11); + arg2 = make_periodic_param(mp_t(-5), mp_t(6), 11); + arg3 = make_random_param(mp_t(0.0001), mp_t(1), 10); + arg4 = make_random_param(mp_t(0.0001), mp_t(1), 100 /*500*/); + arg5 = make_periodic_param(mp_t(1), mp_t(41), 10); + + arg1.type |= dummy_param; + arg2.type |= dummy_param; + arg3.type |= dummy_param; + arg4.type |= dummy_param; + arg5.type |= dummy_param; + + // comment out all but one of the following when running + // or this program will take forever to complete! + //data.insert(beta_data_generator(), arg1, arg2, arg3); + //data.insert(beta_data_generator_medium(), arg4); + //data.insert(beta_data_generator_small(), arg4); + data.insert(beta_data_generator_int(), arg5, arg5, arg3); + + test_data<mp_t>::const_iterator i, j; + i = data.begin(); + j = data.end(); + while(i != j) + { + mp_t v1 = beta((*i)[0], (*i)[1], (*i)[2]); + mp_t v2 = relative_error(v1, (*i)[3]); + std::string s = boost::lexical_cast<std::string>((*i)[3]); + mp_t v3 = boost::lexical_cast<mp_t>(s); + mp_t v4 = relative_error(v3, (*i)[3]); + if(v2 > 1e-40) + { + std::cout << v2 << std::endl; + } + if(v4 > 1e-60) + { + std::cout << v4 << std::endl; + } + ++ i; + } + + std::cout << "Enter name of test data file [default=ibeta_data.ipp]"; + std::string line; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "ibeta_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "ibeta_data"); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/ibeta_derivative_data.cpp b/src/boost/libs/math/tools/ibeta_derivative_data.cpp new file mode 100644 index 00000000..80e01907 --- /dev/null +++ b/src/boost/libs/math/tools/ibeta_derivative_data.cpp @@ -0,0 +1,68 @@ +// (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 <boost/math/special_functions/gamma.hpp> +#include <boost/math/special_functions/beta.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <map> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +#include <libs/math/test/table_type.hpp> + +#define T double +#define SC_(x) static_cast<double>(x) +#include <libs/math/test/ibeta_int_data.ipp> + +int main(int, char* []) +{ + std::cout << "Enter name of test data file [default=ibeta_derivative_data.ipp]"; + std::string line; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "ibeta_derivative_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + + ofs << + "// (C) Copyright John Maddock 2006.\n" + "// Use, modification and distribution are subject to the\n" + "// Boost Software License, Version 1.0. (See accompanying file\n" + "// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" + "\n\n" + "static const boost::array<boost::array<typename table_type<T>::type, 4>, " << ibeta_int_data.size() << "> ibeta_derivative_small_data = { {\n"; + + + for(unsigned i = 0; i < ibeta_int_data.size(); ++i) + { + mp_t a(ibeta_int_data[i][0]); + mp_t b(ibeta_int_data[i][1]); + mp_t x(ibeta_int_data[i][2]); + + std::cout << a << std::endl; + std::cout << b << std::endl; + std::cout << x << std::endl; + + mp_t bet = exp(boost::math::lgamma(a) + boost::math::lgamma(b) - boost::math::lgamma(a + b)); + mp_t d = pow(1 - x, b - 1) * pow(x, a - 1) / bet; + + ofs << "{{ SC_(" << a << "), SC_(" << b << "), SC_(" << x << "), SC_(" << d << ") }}\n"; + } + + ofs << "}};\n\n"; + + + return 0; +} + + diff --git a/src/boost/libs/math/tools/ibeta_inv_data.cpp b/src/boost/libs/math/tools/ibeta_inv_data.cpp new file mode 100644 index 00000000..17136fc8 --- /dev/null +++ b/src/boost/libs/math/tools/ibeta_inv_data.cpp @@ -0,0 +1,86 @@ +// (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 <boost/math/special_functions/beta.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; + +// +// Force trunctation to float precision of input values: +// we must ensure that the input values are exactly representable +// in whatever type we are testing, or the output values will all +// be thrown off: +// +float external_f; +float force_truncate(const float* f) +{ + external_f = *f; + return external_f; +} + +float truncate_to_float(mp_t r) +{ + float f = boost::math::tools::real_cast<float>(r); + return force_truncate(&f); +} + +boost::mt19937 rnd; +boost::uniform_real<float> ur_a(1.0F, 5.0F); +boost::variate_generator<boost::mt19937, boost::uniform_real<float> > gen(rnd, ur_a); +boost::uniform_real<float> ur_a2(0.0F, 100.0F); +boost::variate_generator<boost::mt19937, boost::uniform_real<float> > gen2(rnd, ur_a2); + +struct ibeta_inv_data_generator +{ + boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t> operator()(mp_t ap, mp_t bp, mp_t x_) + { + float a = truncate_to_float(real_cast<float>(gen() * pow(mp_t(10), ap))); + float b = truncate_to_float(real_cast<float>(gen() * pow(mp_t(10), bp))); + float x = truncate_to_float(real_cast<float>(x_)); + std::cout << a << " " << b << " " << x << std::flush; + mp_t inv = boost::math::ibeta_inv(mp_t(a), mp_t(b), mp_t(x)); + std::cout << " " << inv << std::flush; + mp_t invc = boost::math::ibetac_inv(mp_t(a), mp_t(b), mp_t(x)); + std::cout << " " << invc << std::endl; + return boost::math::make_tuple(a, b, x, inv, invc); + } +}; + +int main(int argc, char*argv []) +{ + bool cont; + std::string line; + + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the inverse incomplete beta function:\n" + " ibeta_inv(a, p) and ibetac_inv(a, q)\n\n"; + + arg1 = make_periodic_param(mp_t(-5), mp_t(6), 11); + arg2 = make_periodic_param(mp_t(-5), mp_t(6), 11); + arg3 = make_random_param(mp_t(0.0001), mp_t(1), 10); + + arg1.type |= dummy_param; + arg2.type |= dummy_param; + arg3.type |= dummy_param; + + data.insert(ibeta_inv_data_generator(), arg1, arg2, arg3); + + line = "ibeta_inv_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "ibeta_inv_data"); + + return 0; +} + diff --git a/src/boost/libs/math/tools/ibeta_invab_data.cpp b/src/boost/libs/math/tools/ibeta_invab_data.cpp new file mode 100644 index 00000000..59a6a774 --- /dev/null +++ b/src/boost/libs/math/tools/ibeta_invab_data.cpp @@ -0,0 +1,91 @@ +// (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 <boost/math/special_functions/beta.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; + +// +// Force trunctation to float precision of input values: +// we must ensure that the input values are exactly representable +// in whatever type we are testing, or the output values will all +// be thrown off: +// +float external_f; +float force_truncate(const float* f) +{ + external_f = *f; + return external_f; +} + +float truncate_to_float(mp_t r) +{ + float f = boost::math::tools::real_cast<float>(r); + return force_truncate(&f); +} + +boost::mt19937 rnd; +boost::uniform_real<float> ur_a(1.0F, 5.0F); +boost::variate_generator<boost::mt19937, boost::uniform_real<float> > gen(rnd, ur_a); +boost::uniform_real<float> ur_a2(0.0F, 100.0F); +boost::variate_generator<boost::mt19937, boost::uniform_real<float> > gen2(rnd, ur_a2); + +struct ibeta_inv_data_generator +{ + boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t, mp_t, mp_t> operator() + (mp_t bp, mp_t x_, mp_t p_) + { + float b = truncate_to_float(real_cast<float>(gen() * pow(mp_t(10), bp))); + float x = truncate_to_float(real_cast<float>(x_)); + float p = truncate_to_float(real_cast<float>(p_)); + std::cout << b << " " << x << " " << p << std::flush; + mp_t inv = boost::math::ibeta_inva(mp_t(b), mp_t(x), mp_t(p)); + std::cout << " " << inv << std::flush; + mp_t invc = boost::math::ibetac_inva(mp_t(b), mp_t(x), mp_t(p)); + std::cout << " " << invc << std::endl; + mp_t invb = boost::math::ibeta_invb(mp_t(b), mp_t(x), mp_t(p)); + std::cout << " " << invb << std::flush; + mp_t invbc = boost::math::ibetac_invb(mp_t(b), mp_t(x), mp_t(p)); + std::cout << " " << invbc << std::endl; + return boost::math::make_tuple(b, x, p, inv, invc, invb, invbc); + } +}; + +int main(int argc, char*argv []) +{ + bool cont; + std::string line; + + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the inverse incomplete beta function:\n" + " ibeta_inva(a, p) and ibetac_inva(a, q)\n\n"; + + arg1 = make_periodic_param(mp_t(-5), mp_t(6), 11); + arg2 = make_random_param(mp_t(0.0001), mp_t(1), 10); + arg3 = make_random_param(mp_t(0.0001), mp_t(1), 10); + + arg1.type |= dummy_param; + arg2.type |= dummy_param; + arg3.type |= dummy_param; + + data.insert(ibeta_inv_data_generator(), arg1, arg2, arg3); + + line = "ibeta_inva_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "ibeta_inva_data"); + + return 0; +} + diff --git a/src/boost/libs/math/tools/igamma_data.cpp b/src/boost/libs/math/tools/igamma_data.cpp new file mode 100644 index 00000000..ba78a534 --- /dev/null +++ b/src/boost/libs/math/tools/igamma_data.cpp @@ -0,0 +1,177 @@ +// (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 <boost/math/special_functions/gamma.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/lexical_cast.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; + +// +// Force trunctation to float precision of input values: +// we must ensure that the input values are exactly representable +// in whatever type we are testing, or the output values will all +// be thrown off: +// +float external_f; +float force_truncate(const float* f) +{ + external_f = *f; + return external_f; +} + +float truncate_to_float(mp_t r) +{ + float f = boost::math::tools::real_cast<float>(r); + return force_truncate(&f); +} + +// +// Our generator takes two arguments, but the second is interpreted +// as an instruction not a value, the second argument won't be placed +// in the output matrix by class test_data, so we add our algorithmically +// derived second argument to the output. +// +struct igamma_data_generator +{ + boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t> operator()(mp_t a, mp_t x) + { + // very naively calculate spots: + mp_t z; + switch((int)real_cast<float>(x)) + { + case 1: + z = truncate_to_float((std::min)(mp_t(1), a/100)); + break; + case 2: + z = truncate_to_float(a / 2); + break; + case 3: + z = truncate_to_float((std::max)(0.9*a, a - 2)); + break; + case 4: + z = a; + break; + case 5: + z = truncate_to_float((std::min)(1.1*a, a + 2)); + break; + case 6: + z = truncate_to_float(a * 2); + break; + case 7: + z = truncate_to_float((std::max)(mp_t(100), a*100)); + break; + default: + BOOST_ASSERT(0 == "Can't get here!!"); + } + + //mp_t g = boost::math::tgamma(a); + mp_t lg = boost::math::tgamma_lower(a, z); + mp_t ug = boost::math::tgamma(a, z); + mp_t rlg = boost::math::gamma_p(a, z); + mp_t rug = boost::math::gamma_q(a, z); + + return boost::math::make_tuple(z, ug, rug, lg, rlg); + } +}; + +struct gamma_inverse_generator +{ + boost::math::tuple<mp_t, mp_t> operator()(const mp_t a, const mp_t p) + { + mp_t x1 = boost::math::gamma_p_inv(a, p); + mp_t x2 = boost::math::gamma_q_inv(a, p); + std::cout << "Inverse for " << a << " " << p << std::endl; + return boost::math::make_tuple(x1, x2); + } +}; + +struct gamma_inverse_generator_a +{ + boost::math::tuple<mp_t, mp_t> operator()(const mp_t x, const mp_t p) + { + mp_t x1 = boost::math::gamma_p_inva(x, p); + mp_t x2 = boost::math::gamma_q_inva(x, p); + std::cout << "Inverse for " << x << " " << p << std::endl; + return boost::math::make_tuple(x1, x2); + } +}; + + +int main(int argc, char*argv []) +{ + bool cont; + std::string line; + + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + if((argc >= 2) && (std::strcmp(argv[1], "-inverse") == 0)) + { + std::cout << "Welcome.\n" + "This program will generate spot tests for the inverse incomplete gamma function:\n" + " gamma_p_inv(a, p) and gamma_q_inv(a, q)\n\n"; + do{ + get_user_parameter_info(arg1, "a"); + get_user_parameter_info(arg2, "p"); + data.insert(gamma_inverse_generator(), arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + } + else if((argc >= 2) && (std::strcmp(argv[1], "-inverse_a") == 0)) + { + std::cout << "Welcome.\n" + "This program will generate spot tests for the inverse incomplete gamma function:\n" + " gamma_p_inva(a, p) and gamma_q_inva(a, q)\n\n"; + do{ + get_user_parameter_info(arg1, "x"); + get_user_parameter_info(arg2, "p"); + data.insert(gamma_inverse_generator_a(), arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + } + else + { + arg2 = make_periodic_param(mp_t(1), mp_t(8), 7); + arg2.type |= boost::math::tools::dummy_param; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the incomplete gamma function:\n" + " gamma(a, z)\n\n"; + + do{ + get_user_parameter_info(arg1, "a"); + data.insert(igamma_data_generator(), arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + } + + std::cout << "Enter name of test data file [default=igamma_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "igamma_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "igamma_data"); + + return 0; +} + diff --git a/src/boost/libs/math/tools/igamma_temme_large_coef.cpp b/src/boost/libs/math/tools/igamma_temme_large_coef.cpp new file mode 100644 index 00000000..61849ab1 --- /dev/null +++ b/src/boost/libs/math/tools/igamma_temme_large_coef.cpp @@ -0,0 +1,206 @@ +// 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 <boost/math/special_functions/log1p.hpp> +#include <boost/math/special_functions/erf.hpp> +#include <boost/math/constants/constants.hpp> +#include <map> +#include <iostream> +#include <iomanip> +#include "mp_t.hpp" + +using namespace std; +using namespace boost::math; + +// +// This program calculates the coefficients of the polynomials +// used for the regularized incomplete gamma functions gamma_p +// and gamma_q when parameter a is large, and sigma is small +// (where sigma = fabs(1 - x/a) ). +// +// See "The Asymptotic Expansion of the Incomplete Gamma Functions" +// N. M. Temme. +// Siam J. Math Anal. Vol 10 No 4, July 1979, p757. +// Coeffient calculation is described from Eq 3.8 (p762) onwards. +// + +// +// Alpha: +// +mp_t alpha(unsigned k) +{ + static map<unsigned, mp_t> data; + if(data.empty()) + { + data[1] = 1; + } + + map<unsigned, mp_t>::const_iterator pos = data.find(k); + if(pos != data.end()) + return (*pos).second; + // + // OK try and calculate the value: + // + mp_t result = alpha(k-1); + for(unsigned j = 2; j <= k-1; ++j) + { + result -= j * alpha(j) * alpha(k-j+1); + } + result /= (k+1); + data[k] = result; + return result; +} + +mp_t gamma(unsigned k) +{ + static map<unsigned, mp_t> data; + + map<unsigned, mp_t>::const_iterator pos = data.find(k); + if(pos != data.end()) + return (*pos).second; + + mp_t result = (k&1) ? -1 : 1; + + for(unsigned i = 1; i <= (2 * k + 1); i += 2) + result *= i; + result *= alpha(2 * k + 1); + data[k] = result; + return result; +} + +mp_t Coeff(unsigned n, unsigned k) +{ + map<unsigned, map<unsigned, mp_t> > data; + if(data.empty()) + data[0][0] = mp_t(-1) / 3; + + map<unsigned, map<unsigned, mp_t> >::const_iterator p1 = data.find(n); + if(p1 != data.end()) + { + map<unsigned, mp_t>::const_iterator p2 = p1->second.find(k); + if(p2 != p1->second.end()) + { + return p2->second; + } + } + + // + // If we don't have the value, calculate it: + // + if(k == 0) + { + // special case: + mp_t result = (n+2) * alpha(n+2); + data[n][k] = result; + return result; + } + // general case: + mp_t result = gamma(k) * Coeff(n, 0) + (n+2) * Coeff(n+2, k-1); + data[n][k] = result; + return result; +} + +void calculate_terms(double sigma, double a, unsigned bits) +{ + cout << endl << endl; + cout << "Sigma: " << sigma << endl; + cout << "A: " << a << endl; + double lambda = 1 - sigma; + cout << "Lambda: " << lambda << endl; + double y = a * (-sigma - log1p(-sigma)); + cout << "Y: " << y << endl; + double z = -sqrt(2 * (-sigma - log1p(-sigma))); + cout << "Z: " << z << endl; + double dom = erfc(sqrt(y)) / 2; + cout << "Erfc term: " << dom << endl; + double lead = exp(-y) / sqrt(2 * constants::pi<double>() * a); + cout << "Remainder factor: " << lead << endl; + double eps = ldexp(1.0, 1 - static_cast<int>(bits)); + double target = dom * eps / lead; + cout << "Target smallest term: " << target << endl; + + unsigned max_n = 0; + + for(unsigned n = 0; n < 10000; ++n) + { + double term = tools::real_cast<double>(Coeff(n, 0) * pow(z, (double)n)); + if(fabs(term) < target) + { + max_n = n-1; + break; + } + } + cout << "Max n required: " << max_n << endl; + + unsigned max_k; + for(unsigned k = 1; k < 10000; ++k) + { + double term = tools::real_cast<double>(Coeff(0, k) * pow(a, -((double)k))); + if(fabs(term) < target) + { + max_k = k-1; + break; + } + } + cout << "Max k required: " << max_k << endl << endl; + + bool code = false; + cout << "Print code [0|1]? "; + cin >> code; + + int prec = 2 + (static_cast<double>(bits) * 3010LL)/10000; + std::cout << std::scientific << std::setprecision(40); + + if(code) + { + cout << " T workspace[" << max_k+1 << "];\n\n"; + for(unsigned k = 0; k <= max_k; ++k) + { + cout << + " static const T C" << k << "[] = {\n"; + for(unsigned n = 0; n < 10000; ++n) + { + double term = tools::real_cast<double>(Coeff(n, k) * pow(a, -((double)k)) * pow(z, (double)n)); + if(fabs(term) < target) + { + break; + } + cout << " " << Coeff(n, k) << "L,\n"; + } + cout << + " };\n" + " workspace[" << k << "] = tools::evaluate_polynomial(C" << k << ", z);\n\n"; + } + cout << " T result = tools::evaluate_polynomial(workspace, 1/a);\n\n"; + } +} + + +int main() +{ + bool cont; + do{ + cont = false; + double sigma; + cout << "Enter max value for sigma (sigma = |1 - x/a|): "; + cin >> sigma; + double a; + cout << "Enter min value for a: "; + cin >> a; + unsigned precision; + cout << "Enter number of bits precision required: "; + cin >> precision; + + calculate_terms(sigma, a, precision); + + cout << "Try again[0|1]: "; + cin >> cont; + + }while(cont); + + + return 0; +} + diff --git a/src/boost/libs/math/tools/inv_hyp_data.cpp b/src/boost/libs/math/tools/inv_hyp_data.cpp new file mode 100644 index 00000000..cff496bf --- /dev/null +++ b/src/boost/libs/math/tools/inv_hyp_data.cpp @@ -0,0 +1,131 @@ +// Copyright John Maddock 2008. +// 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 <boost/math/constants/constants.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace std; + +struct asinh_data_generator +{ + mp_t operator()(mp_t z) + { + std::cout << z << " "; + mp_t result = log(z + sqrt(z * z + 1)); + std::cout << result << std::endl; + return result; + } +}; + +struct acosh_data_generator +{ + mp_t operator()(mp_t z) + { + std::cout << z << " "; + mp_t result = log(z + sqrt(z * z - 1)); + std::cout << result << std::endl; + return result; + } +}; + +struct atanh_data_generator +{ + mp_t operator()(mp_t z) + { + std::cout << z << " "; + mp_t result = log((z + 1) / (1 - z)) / 2; + std::cout << result << std::endl; + return result; + } +}; + +int main(int argc, char*argv []) +{ + parameter_info<mp_t> arg1; + test_data<mp_t> data; + std::ofstream ofs; + + bool cont; + std::string line; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the inverse hyperbolic sin function:\n"; + + do{ + if(0 == get_user_parameter_info(arg1, "z")) + return 1; + data.insert(asinh_data_generator(), arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=asinh_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "asinh_data.ipp"; + ofs.open(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "asinh_data"); + data.clear(); + + std::cout << "Welcome.\n" + "This program will generate spot tests for the inverse hyperbolic cos function:\n"; + + do{ + if(0 == get_user_parameter_info(arg1, "z")) + return 1; + data.insert(acosh_data_generator(), arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=acosh_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "acosh_data.ipp"; + ofs.close(); + ofs.open(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "acosh_data"); + data.clear(); + + std::cout << "Welcome.\n" + "This program will generate spot tests for the inverse hyperbolic tan function:\n"; + + do{ + if(0 == get_user_parameter_info(arg1, "z")) + return 1; + data.insert(atanh_data_generator(), arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=atanh_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "atanh_data.ipp"; + ofs.close(); + ofs.open(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "atanh_data"); + + return 0; +} + diff --git a/src/boost/libs/math/tools/jacobi_zeta_data.cpp b/src/boost/libs/math/tools/jacobi_zeta_data.cpp new file mode 100644 index 00000000..ded65230 --- /dev/null +++ b/src/boost/libs/math/tools/jacobi_zeta_data.cpp @@ -0,0 +1,64 @@ +// 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 <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <boost/math/special_functions/ellint_1.hpp> +#include <boost/math/special_functions/ellint_2.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +mp_t jacobi_zeta(mp_t phi, mp_t k) +{ + return ellint_2(k, phi) - ellint_2(k) * ellint_1(k, phi) / ellint_1(k); +} + +int cpp_main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + if(0 == get_user_parameter_info(arg1, "phi")) + return 1; + if(0 == get_user_parameter_info(arg2, "k")) + return 1; + + mp_t(*fp)(mp_t, mp_t) = &jacobi_zeta; + data.insert(fp, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=jacobi_zeta_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "jacobi_zeta_data.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/laguerre_data.cpp b/src/boost/libs/math/tools/laguerre_data.cpp new file mode 100644 index 00000000..b1777b15 --- /dev/null +++ b/src/boost/libs/math/tools/laguerre_data.cpp @@ -0,0 +1,101 @@ +// (C) Copyright John Maddock 2007. +// 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 <boost/math/tools/test_data.hpp> +#include <boost/math/special_functions/laguerre.hpp> +#include <boost/math/special_functions/gamma.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + + +template<class T> +boost::math::tuple<T, T, T> laguerre2_data(T n, T x) +{ + n = floor(n); + T r1 = laguerre(boost::math::tools::real_cast<unsigned>(n), x); + return boost::math::make_tuple(n, x, r1); +} + +template<class T> +boost::math::tuple<T, T, T, T> laguerre3_data(T n, T m, T x) +{ + n = floor(n); + m = floor(m); + T r1 = laguerre(real_cast<unsigned>(n), real_cast<unsigned>(m), x); + return boost::math::make_tuple(n, m, x, r1); +} + +int main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 2) + return 1; + + if(strcmp(argv[1], "--laguerre2") == 0) + { + do{ + if(0 == get_user_parameter_info(arg1, "n")) + return 1; + if(0 == get_user_parameter_info(arg2, "x")) + return 1; + arg1.type |= dummy_param; + arg2.type |= dummy_param; + + data.insert(&laguerre2_data<mp_t>, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + } + else if(strcmp(argv[1], "--laguerre3") == 0) + { + do{ + if(0 == get_user_parameter_info(arg1, "n")) + return 1; + if(0 == get_user_parameter_info(arg2, "m")) + return 1; + if(0 == get_user_parameter_info(arg3, "x")) + return 1; + arg1.type |= dummy_param; + arg2.type |= dummy_param; + arg3.type |= dummy_param; + + data.insert(&laguerre3_data<mp_t>, arg1, arg2, arg3); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + } + + + std::cout << "Enter name of test data file [default=laguerre.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "laguerre.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + diff --git a/src/boost/libs/math/tools/lambert_w_errors_graph.cpp b/src/boost/libs/math/tools/lambert_w_errors_graph.cpp new file mode 100644 index 00000000..45baa200 --- /dev/null +++ b/src/boost/libs/math/tools/lambert_w_errors_graph.cpp @@ -0,0 +1,262 @@ +// Copyright Paul A. Bristow 2017, 2018 +// Copyright John Z. Maddock 2017 + +// 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). + +/*! \brief Graph showing differences of Lambert W function double from nearest representable values. + +\details + +*/ + +#include <boost/math/special_functions/lambert_w.hpp> +using boost::math::lambert_w0; +using boost::math::lambert_wm1; +#include <boost/math/special_functions.hpp> +using boost::math::isfinite; +#include <boost/svg_plot/svg_2d_plot.hpp> +using namespace boost::svg; + +// For higher precision computation of Lambert W. +#include <boost/multiprecision/cpp_bin_float.hpp> +#include <boost/math/special_functions/next.hpp> // For float_distance. +using boost::math::float_distance; + +#include <iostream> +// using std::cout; +// using std::endl; +#include <exception> +#include <stdexcept> +#include <string> +#include <array> +#include <vector> +#include <utility> +using std::pair; +#include <map> +using std::map; +#include <set> +using std::multiset; +#include <limits> +using std::numeric_limits; +#include <cmath> // exp + +/*! +*/ + + +int main() +{ + try + { + std::cout << "Lambert W errors graph." << std::endl; + using boost::multiprecision::cpp_bin_float_50; + using boost::multiprecision::cpp_bin_float_quad; + + typedef cpp_bin_float_quad HPT; // High precision type. + + using boost::math::float_distance; + using boost::math::policies::precision; + using boost::math::policies::digits10; + using boost::math::policies::digits2; + using boost::math::policies::policy; + + std::cout.precision(std::numeric_limits<double>::max_digits10); + + //[lambert_w_graph_1 + + //] [/lambert_w_graph_1] + { + std::map<const double, double> w0s; // Lambert W0 branch values, default double precision, digits2 = 53. + std::map<const double, double> w0s_50; // Lambert W0 branch values digits2 = 50. + + int max_distance = 0; + int total_distance = 0; + int count = 0; + const int bits = 7; + double min_z = -0.367879; // Close to singularity at -0.3678794411714423215955237701614608727 -exp(-1) + //double min_z = 0.06; // Above 0.05 switch point. + double max_z = 99.99; + double step_z = 0.05; + + for (HPT z = min_z; z < max_z; z += step_z) + { + double zd = static_cast<double>(z); + double w0d = lambert_w0(zd); // double result from same default. + HPT w0_best = lambert_w0<HPT>(z); + double w0_best_d = static_cast<double>(w0_best); // reference result. + // w0s[zd] = (w0d - w0_best_d); // absolute difference. + // w0s[z] = 100 * (w0 - w0_best) / w0_best; // difference relative % . + w0s[zd] = float_distance<double>(w0d, w0_best_d); // difference in bits. + double fd = float_distance<double>(w0d, w0_best_d); + int distance = static_cast<int>(fd); + int abs_distance = abs(distance); + + // std::cout << count << " " << zd << " " << w0d << " " << w0_best_d + // << ", Difference = " << w0d - w0_best_d << ", % = " << (w0d - w0_best_d) / w0d << ", Distance = " << distance << std::endl; + + total_distance += abs_distance; + if (abs_distance > max_distance) + { + max_distance = abs_distance; + } + count++; + } // for z + std::cout << "points " << count << std::endl; + std::cout.precision(3); + std::cout << "max distance " << max_distance << ", total distances = " << total_distance + << ", mean distance " << (float)total_distance / count << std::endl; + + typedef std::map<const double, double>::const_iterator Map_Iterator; + + /* for (std::map<const double, double>::const_iterator it = w0s.begin(); it != w0s.end(); ++it) + { + std::cout << " " << *(it) << "\n"; + } + */ + svg_2d_plot data_plot_0; // <-0.368, -46> <-0.358, -4> <-0.348, 1>... + + data_plot_0.title("Lambert W0 function differences from 'best' for double.") + .title_font_size(11) + .x_size(400) + .y_size(200) + .legend_on(false) + //.legend_font_weight(1) + .x_label("z") + .y_label("W0 difference (bits)") + //.x_label_on(true) + //.y_label_on(true) + //.xy_values_on(false) + .x_range(-1, 100.) + .y_range(-4., +4.) + .x_major_interval(10.) + .y_major_interval(2.) + .x_major_grid_on(true) + .y_major_grid_on(true) + .x_label_font_size(9) + .y_label_font_size(9) + //.x_values_on(true) + //.y_values_on(true) + .y_values_rotation(horizontal) + //.plot_window_on(true) + .x_values_precision(3) + .y_values_precision(3) + .coord_precision(3) // Needed to avoid stepping on curves. + //.coord_precision(4) // Needed to avoid stepping on curves. + .copyright_holder("Paul A. Bristow") + .copyright_date("2018") + //.background_border_color(black); + ; + + + data_plot_0.plot(w0s, "W0 branch").line_color(red).shape(none).line_on(true).bezier_on(false).line_width(0.2); + //data_plot.plot(wm1s, "W-1 branch").line_color(blue).shape(none).line_on(true).bezier_on(false).line_width(1); + data_plot_0.write("./lambert_w0_errors_graph"); + + } // end W0 branch plot. + { // Repeat for Lambert W-1 branch. + + std::map<const double, double> wm1s; // Lambert W-1 branch values. + std::map<const double, double> wm1s_50; // Lambert Wm1 branch values digits2 = 50. + + int max_distance = 0; + int total_distance = 0; + int count = 0; + const int bits = 7; + double min_z = -0.367879; // Close to singularity at -0.3678794411714423215955237701614608727 -exp(-1) + //double min_z = 0.06; // Above 0.05 switch point. + double max_z = -0.0001; + double step_z = 0.001; + + for (HPT z = min_z; z < max_z; z += step_z) + { + if (z > max_z) + { + break; + } + double zd = static_cast<double>(z); + double wm1d = lambert_wm1(zd); // double result from same default. + HPT wm1_best = lambert_wm1<HPT>(z); + double wm1_best_d = static_cast<double>(wm1_best); // reference result. + // wm1s[zd] = (wm1d - wm1_best_d); // absolute difference. + // wm1s[z] = 100 * (wm1 - wm1_best) / wm1_best; // difference relative % . + wm1s[zd] = float_distance<double>(wm1d, wm1_best_d); // difference in bits. + double fd = float_distance<double>(wm1d, wm1_best_d); + int distance = static_cast<int>(fd); + int abs_distance = abs(distance); + + //std::cout << count << " " << zd << " " << wm1d << " " << wm1_best_d + // << ", Difference = " << wm1d - wm1_best_d << ", % = " << (wm1d - wm1_best_d) / wm1d << ", Distance = " << distance << std::endl; + + total_distance += abs_distance; + if (abs_distance > max_distance) + { + max_distance = abs_distance; + } + count++; + + } // for z + std::cout << "points " << count << std::endl; + std::cout.precision(3); + std::cout << "max distance " << max_distance << ", total distances = " << total_distance + << ", mean distance " << (float)total_distance / count << std::endl; + + typedef std::map<const double, double>::const_iterator Map_Iterator; + + /* for (std::map<const double, double>::const_iterator it = wm1s.begin(); it != wm1s.end(); ++it) + { + std::cout << " " << *(it) << "\n"; + } + */ + svg_2d_plot data_plot_m1; // <-0.368, -46> <-0.358, -4> <-0.348, 1>... + + data_plot_m1.title("Lambert W-1 function differences from 'best' for double.") + .title_font_size(11) + .x_size(400) + .y_size(200) + .legend_on(false) + //.legend_font_weight(1) + .x_label("z") + .y_label("W-1 difference (bits)") + .x_range(-0.39, +0.0001) + .y_range(-4., +4.) + .x_major_interval(0.1) + .y_major_interval(2.) + .x_major_grid_on(true) + .y_major_grid_on(true) + .x_label_font_size(9) + .y_label_font_size(9) + //.x_values_on(true) + //.y_values_on(true) + .y_values_rotation(horizontal) + //.plot_window_on(true) + .x_values_precision(3) + .y_values_precision(3) + .coord_precision(3) // Needed to avoid stepping on curves. + //.coord_precision(4) // Needed to avoid stepping on curves. + .copyright_holder("Paul A. Bristow") + .copyright_date("2018") + //.background_border_color(black); + ; + data_plot_m1.plot(wm1s, "W-1 branch").line_color(darkblue).shape(none).line_on(true).bezier_on(false).line_width(0.2); + data_plot_m1.write("./lambert_wm1_errors_graph"); + } + } + catch (std::exception& ex) + { + std::cout << ex.what() << std::endl; + } +} // int main() + + /* + //[lambert_w_errors_graph_1_output + Lambert W errors graph. + points 2008 + max distance 46, total distances = 717, mean distance 0.357 + + points 368 + max distance 23, total distances = 329, mean distance 0.894 + + //] [/lambert_w_errors_graph_1_output] + */ diff --git a/src/boost/libs/math/tools/lambert_w_high_reference_values.cpp b/src/boost/libs/math/tools/lambert_w_high_reference_values.cpp new file mode 100644 index 00000000..11dd4306 --- /dev/null +++ b/src/boost/libs/math/tools/lambert_w_high_reference_values.cpp @@ -0,0 +1,182 @@ +// \modular-boost\libs\math\test\lambert_w_high_reference_values.cpp + +// Copyright Paul A. Bristow 2017. +// 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) + +// Write a C++ file \lambert_w_mp_hi_values.ipp +// containing arrays of z arguments and 100 decimal digit precision lambert_w0(z) reference values. +// These can be used in tests of precision of less-precise types like +// built-in float, double, long double and quad and cpp_dec_float_50. + +// These cover the range from 0.5 to (std::numeric_limits<>::max)(); +// The Fukushima algorithm changes from a series function for all z > 0.5. + +// Multiprecision types: +//#include <boost/multiprecision/cpp_bin_float.hpp> +#include <boost/multiprecision/cpp_dec_float.hpp> // boost::multiprecision::cpp_dec_float_100 +using boost::multiprecision::cpp_dec_float_100; + +#include <boost/math/special_functions/lambert_w.hpp> // +using boost::math::lambert_w0; +using boost::math::lambert_wm1; + +#include <iostream> +// using std::cout; using std::std::endl; using std::ios; using std::std::cerr; +#include <iomanip> +using std::setprecision; +using std::showpoint; +#include <fstream> +using std::ofstream; +#include <cassert> +#include <cfloat> // for DBL_EPS etc +#include <limits> // for numeric limits. +//#include <ctype> +#include <string> + +const long double eps = std::numeric_limits<long double>::epsilon(); + +// Creates if no file exists, & uses default overwrite/ ios::replace. +const char filename[] = "lambert_w_high_reference_values.ipp"; // +std::ofstream fout(filename, std::ios::out); + +typedef cpp_dec_float_100 RealType; // 100 decimal digits for the value fed to macro BOOST_MATH_TEST_VALUE. +// Could also use cpp_dec_float_50 or cpp_bin_float types. + +const int no_of_tests = 450; // 500 overflows float. + +static const float min_z = 0.5F; // for element[0] + +int main() +{ // Make C++ file containing Lambert W test values. + std::cout << filename << " "; + std::cout << std::endl; + std::cout << "Lambert W0 decimal digit precision values for high z argument values." << std::endl; + + if (!fout.is_open()) + { // File failed to open OK. + std::cerr << "Open file " << filename << " failed!" << std::endl; + std::cerr << "errno " << errno << std::endl; + return -1; + } + try + { + int output_precision = std::numeric_limits<RealType>::digits10; + // cpp_dec_float_100 is ample precision and + // has several extra bits internally so max_digits10 are not needed. + fout.precision(output_precision); + fout << std::showpoint << std::endl; // Do show trailing zeros. + + // Intro for RealType values. + std::cout << "Lambert W test values written to file " << filename << std::endl; + fout << + "\n" + "// A collection of big Lambert W test values computed using " + << output_precision << " decimal digits precision.\n" + "// C++ floating-point type is " << "RealType." "\n" + "\n" + "// Written by " << __FILE__ << " " << __TIMESTAMP__ << "\n" + + "\n" + "// Copyright Paul A. Bristow 2017." "\n" + "// Distributed under the Boost Software License, Version 1.0." "\n" + "// (See accompanying file LICENSE_1_0.txt" "\n" + "// or copy at http://www.boost.org/LICENSE_1_0.txt)" "\n" + << std::endl; + + fout << "// Size of arrays of arguments z and Lambert W" << std::endl; + fout << "static const unsigned int noof_tests = " << no_of_tests << ";" << std::endl; + + // Declare arrays of z and Lambert W. + fout << "\n// Declare arrays of arguments z and Lambert W(z)" << std::endl; + fout << + "\n" + "template <typename RealType>""\n" + "static RealType zs[" << no_of_tests << "];" + << std::endl; + + fout << + "\n" + "template <typename RealType>""\n" + "static RealType ws[" << no_of_tests << "];" + << std::endl; + + fout << "// The values are defined using the macro BOOST_MATH_TEST_VALUE to ensure\n" + "// that both built-in and multiprecision types are correctly initialiased with full precision.\n" + "// built-in types like float, double require a floating-point literal like 3.14,\n" + "// but multiprecision types require a decimal digit string like \"3.14\".\n" + "// Numerical values are chosen to avoid exactly representable values." + << std::endl; + + static const RealType min_z = 0.6; // for element[0] + + const RealType max_z = (std::numeric_limits<float>::max)() / 10; // (std::numeric_limits<float>::max)() to make sure is OK for all floating-point types. + // Less a bit as lambert_w0(max) may be inaccurate. + const RealType step_size = 0.5F; // Increment step size. + const RealType step_factor = 2.f; // Multiple factor, typically 2, 5 or 10. + const int step_modulo = 5; + + RealType z = min_z; + + // Output function to initialize array of arguments z and Lambert W. + fout << + "\n" + << "template <typename RealType>\n" + "void init_zws()\n" + "{\n"; + + for (size_t index = 0; (index != no_of_tests); index++) + { + fout + << " zs<RealType>[" << index << "] = BOOST_MATH_TEST_VALUE(RealType, " + << z // Since start with converting a float may get lots of usefully random digits. + << ");" + << std::endl; + + fout + << " ws<RealType>[" << index << "] = BOOST_MATH_TEST_VALUE(RealType, " + << lambert_w0(z) + << ");" + << std::endl; + + if ((index % step_modulo) == 0) + { + z *= step_factor; // + } + z += step_size; + if (z >= max_z) + { // Don't go over max for float. + std::cout << "too big z" << std::endl; + break; + } + } // for index + fout << "};" << std::endl; + + fout << "// End of lambert_w_mp_high_values.ipp " << std::endl; + } + catch (std::exception& ex) + { + std::cout << "Exception " << ex.what() << std::endl; + } + + fout.close(); + + std::cout << no_of_tests << " Lambert_w0 values written to files " << __TIMESTAMP__ << std::endl; + return 0; +} // main + + +/* +A few spot checks again Wolfram: + + zs<RealType>[1] = BOOST_MATH_TEST_VALUE(RealType, 1.6999999999999999555910790149937383830547332763671875); + ws<RealType>[1] = BOOST_MATH_TEST_VALUE(RealType, 0.7796011225311008662356536916883580556792500749037209859530390902424444585607630246126725241921761054); + Wolfram 0.7796011225311008662356536916883580556792500749037209859530390902424444585607630246126725241921761054 + + zs<RealType>[99] = BOOST_MATH_TEST_VALUE(RealType, 3250582.599999999976716935634613037109375); + ws<RealType>[99] = BOOST_MATH_TEST_VALUE(RealType, 12.47094339016839065212822905567651460418204106065566910956134121802725695306834966790193342511971825); + Wolfram 12.47094339016839065212822905567651460418204106065566910956134121802725695306834966790193342511971825 + +*/ + diff --git a/src/boost/libs/math/tools/lambert_w_lookup_table_generator.cpp b/src/boost/libs/math/tools/lambert_w_lookup_table_generator.cpp new file mode 100644 index 00000000..8d4ebe1d --- /dev/null +++ b/src/boost/libs/math/tools/lambert_w_lookup_table_generator.cpp @@ -0,0 +1,469 @@ +// Lambert W lookup table generator lambert_w_lookup_table_generator.cpp + +//! \file +//! Output a table of precomputed array values for Lambert W0 and W-1, +//! and square roots and halves, and powers of e, +// as a .ipp file for use by lambert_w.hpp. + +//! \details Output as long double precision (suffix L) using Boost.Multiprecision +//! to 34 decimal digits precision to cater for platforms that have 128-bit long double. +//! The function bisection can then use any built-in floating-point type, +//! which may have different precision and speed on different platforms. +//! The actual builtin floating-point type of the arrays is chosen by a +//! typedef in \modular-boost\libs\math\include\boost\math\special_functions\lambert_w.hpp +//! by default, for example: typedef double lookup_t; + + +// This includes lookup tables for both branches W0 and W-1. +// Only W-1 is needed by current code that uses JM rational Polynomials, +// but W0 is kept (for now) to allow comparison with the previous FKDVPB version +// that uses lookup for W0 branch as well as W-1. + +#include <boost/config.hpp> +#include <boost/math/constants/constants.hpp> // For exp_minus_one == 3.67879441171442321595523770161460867e-01. +using boost::math::constants::exp_minus_one; // 0.36787944 +using boost::math::constants::root_e; // 1.64872 +#include <boost/multiprecision/cpp_bin_float.hpp> +using boost::multiprecision::cpp_bin_float_quad; +using boost::multiprecision::cpp_bin_float_50; + +#include <iostream> +#include <fstream> +#include <typeinfo> + +/* +typedef double lookup_t; // Type for lookup table (double or float?) + +BOOST_STATIC_CONSTEXPR std::size_t noof_sqrts = 12; +BOOST_STATIC_CONSTEXPR lookup_t a[noof_sqrts] = // 0.6065 0.7788, 0.8824 ... 0.9997, sqrt of previous elements. +{ +0.60653065971263342, 0.77880078307140487, 0.8824969025845954, 0.93941306281347579, 0.96923323447634408, 0.98449643700540841, +0.99221793826024351, 0.99610136947011749, 0.99804878110747547, 0.99902391418197566, 0.99951183793988937, 0.99975588917489722 +}; +BOOST_STATIC_CONSTEXPR lookup_t b[noof_sqrts] = // 0.5 0.25 0.125, 0.0625 ... 0.0002441, halves of previous elements. +{ 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625, 0.0078125, 0.00390625, 0.001953125, 0.0009765625, 0.00048828125, 0.000244140625 }; + +BOOST_STATIC_CONSTEXPR size_t noof_w0zs = 65; +BOOST_STATIC_CONSTEXPR lookup_t g[noof_w0zs] = // lambert_w[k] for W0 branch. 0 2.7182 14.77 60.2566 ... 1.445e+29 3.990e+29. +{ 0., 2.7182818284590452, 14.7781121978613, 60.256610769563003, 218.39260013257696, 742.06579551288302, 2420.5727609564107, 7676.4321089992102, +23847.663896333826, 72927.755348178456, 220264.65794806717, 658615.558867176, 1953057.4970280471, 5751374.0961159665, 16836459.978306875, 49035260.58708166, +142177768.32812596, 410634196.81078007, 1181879444.4719492, 3391163718.300558, 9703303908.1958056, 27695130424.147509, 78868082614.895014, 224130479263.72476, +635738931116.24334, 1800122483434.6468, 5088969845149.8079, 14365302496248.563, 40495197800161.305, 114008694617177.22, 320594237445733.86, +900514339622670.18, 2526814725845782.2, 7083238132935230.1, 19837699245933466., 55510470830970076., 1.5520433569614703e+17, 4.3360826779369662e+17, +1.2105254067703227e+18, 3.3771426165357561e+18, 9.4154106734807994e+18, 2.6233583234732253e+19, 7.3049547543861044e+19, 2.032970971338619e+20, +5.6547040503180956e+20, 1.5720421975868293e+21, 4.3682149334771265e+21, 1.2132170565093317e+22, 3.3680332378068632e+22, 9.3459982052259885e+22, +2.5923527642935362e+23, 7.1876803203773879e+23, 1.99212416037262e+24, 5.5192924995054165e+24, 1.5286067837683347e+25, 4.2321318958281094e+25, +1.1713293177672778e+26, 3.2408603996214814e+26, 8.9641258264226028e+26, 2.4787141382364034e+27, 6.8520443388941057e+27, 1.8936217407781711e+28, +5.2317811346197018e+28, 1.4450833904658542e+29, 3.9904954117194348e+29 +}; + +BOOST_STATIC_CONSTEXPR std::size_t noof_wm1zs = 66; +BOOST_STATIC_CONSTEXPR lookup_t e[noof_wm1zs] = // lambert_w[k] for W-1 branch. 2.7182 1. 0.3678 0.1353 0.04978 ... 4.359e-28 1.603e-28 +{ +2.7182818284590452, 1., 0.36787944117144232, 0.13533528323661269, 0.049787068367863943, 0.01831563888873418, 0.0067379469990854671, +0.0024787521766663584, 0.00091188196555451621, 0.00033546262790251184, 0.00012340980408667955, 4.5399929762484852e-05, 1.6701700790245659e-05, +6.1442123533282098e-06, 2.2603294069810543e-06, 8.3152871910356788e-07, 3.0590232050182579e-07, 1.1253517471925911e-07, 4.1399377187851667e-08, +1.5229979744712628e-08, 5.6027964375372675e-09, 2.0611536224385578e-09, 7.5825604279119067e-10, 2.7894680928689248e-10, 1.026187963170189e-10, +3.7751345442790977e-11, 1.3887943864964021e-11, 5.1090890280633247e-12, 1.8795288165390833e-12, 6.914400106940203e-13, 2.5436656473769229e-13, +9.3576229688401746e-14, 3.4424771084699765e-14, 1.2664165549094176e-14, 4.6588861451033974e-15, 1.713908431542013e-15, 6.3051167601469894e-16, +2.3195228302435694e-16, 8.5330476257440658e-17, 3.1391327920480296e-17, 1.1548224173015786e-17, 4.248354255291589e-18, 1.5628821893349888e-18, +5.7495222642935598e-19, 2.1151310375910805e-19, 7.7811322411337965e-20, 2.8625185805493936e-20, 1.0530617357553812e-20, 3.8739976286871871e-21, +1.4251640827409351e-21, 5.2428856633634639e-22, 1.9287498479639178e-22, 7.0954741622847041e-23, 2.6102790696677048e-23, 9.602680054508676e-24, +3.532628572200807e-24, 1.2995814250075031e-24, 4.7808928838854691e-25, 1.7587922024243116e-25, 6.4702349256454603e-26, 2.3802664086944006e-26, +8.7565107626965203e-27, 3.2213402859925161e-27, 1.185064864233981e-27, 4.359610000063081e-28, 1.6038108905486378e-28 +}; + +lambert_w0 version of array from Fukushima + +// lambert_w[k] for W-1 branch. 2.7182 1. 0.3678 0.1353 0.04978 ... 4.359e-28 1.603e-28 +e: 2.7182818284590452, 1., 0.36787944117144232, 0.13533528323661269, 0.049787068367863943, 0.01831563888873418, 0.0067379469990854671, +0.0024787521766663584, 0.00091188196555451621, 0.00033546262790251184, 0.00012340980408667955, 4.5399929762484852e-05, 1.6701700790245659e-05, +6.1442123533282098e-06, 2.2603294069810543e-06, 8.3152871910356788e-07, 3.0590232050182579e-07, 1.1253517471925911e-07, 4.1399377187851667e-08, +1.5229979744712628e-08, 5.6027964375372675e-09, 2.0611536224385578e-09, 7.5825604279119067e-10, 2.7894680928689248e-10, 1.026187963170189e-10, +3.7751345442790977e-11, 1.3887943864964021e-11, 5.1090890280633247e-12, 1.8795288165390833e-12, 6.914400106940203e-13, 2.5436656473769229e-13, +9.3576229688401746e-14, 3.4424771084699765e-14, 1.2664165549094176e-14, 4.6588861451033974e-15, 1.713908431542013e-15, 6.3051167601469894e-16, +2.3195228302435694e-16, 8.5330476257440658e-17, 3.1391327920480296e-17, 1.1548224173015786e-17, 4.248354255291589e-18, 1.5628821893349888e-18, +5.7495222642935598e-19, 2.1151310375910805e-19, 7.7811322411337965e-20, 2.8625185805493936e-20, 1.0530617357553812e-20, 3.8739976286871871e-21, +1.4251640827409351e-21, 5.2428856633634639e-22, 1.9287498479639178e-22, 7.0954741622847041e-23, 2.6102790696677048e-23, 9.602680054508676e-24, +3.532628572200807e-24, 1.2995814250075031e-24, 4.7808928838854691e-25, 1.7587922024243116e-25, 6.4702349256454603e-26, 2.3802664086944006e-26, +8.7565107626965203e-27, 3.2213402859925161e-27, 1.185064864233981e-27, 4.359610000063081e-28, 1.6038108905486378e-28 + +// lambert_w[k] for W0 branch. 0 2.7182 14.77 60.2566 ... 1.445e+29 3.990e+29. + +g: 0, 2.7182818284590452, 14.7781121978613, 60.256610769563003, 218.39260013257696, 742.06579551288302, 2420.5727609564107, 7676.4321089992102, +23847.663896333826, 72927.755348178456, 220264.65794806717, 658615.558867176, 1953057.4970280471, 5751374.0961159665, 16836459.978306875, 49035260.58708166, +142177768.32812596, 410634196.81078007, 1181879444.4719492, 3391163718.300558, 9703303908.1958056, 27695130424.147509, 78868082614.895014, 224130479263.72476, +635738931116.24334, 1800122483434.6468, 5088969845149.8079, 14365302496248.563, 40495197800161.305, 114008694617177.22, 320594237445733.86, +900514339622670.18, 2526814725845782.2, 7083238132935230.1, 19837699245933466, 55510470830970076, 1.5520433569614703e+17, 4.3360826779369662e+17, +1.2105254067703227e+18, 3.3771426165357561e+18, 9.4154106734807994e+18, 2.6233583234732253e+19, 7.3049547543861044e+19, 2.032970971338619e+20, +5.6547040503180956e+20, 1.5720421975868293e+21, 4.3682149334771265e+21, 1.2132170565093317e+22, 3.3680332378068632e+22, 9.3459982052259885e+22, +2.5923527642935362e+23, 7.1876803203773879e+23, 1.99212416037262e+24, 5.5192924995054165e+24, 1.5286067837683347e+25, 4.2321318958281094e+25, +1.1713293177672778e+26, 3.2408603996214814e+26, 8.9641258264226028e+26, 2.4787141382364034e+27, 6.8520443388941057e+27, 1.8936217407781711e+28, +5.2317811346197018e+28, 1.4450833904658542e+29, 3.9904954117194348e+29 + + +lambert_wm1 version of arrays from Fukushima +e: 2.7182817459106445 7.3890557289123535 20.085535049438477 54.59814453125 148.41314697265625 403.42874145507813 1096.6329345703125 2980.957275390625 8103.08154296875 22026.458984375 59874.12109375 162754.734375 442413.21875 1202603.75 3269015.75 8886106 24154940 65659932 178482192 485164896 1318814848 3584910336 9744796672 26489102336 72004845568 195729457152 532047822848 1446255919104 3931331100672 10686465835008 29048824659968 78962889850880 214643389759488 583461240832000 1586012102852608 4311227773747200 11719131799748608 31855901283450880 86593318145753088 2.3538502982225101e+17 6.398428560008151e+17 1.7392731886358364e+18 4.7278345784949473e+18 1.2851586685678387e+19 3.493423319351296e+19 9.4961089747571704e+19 2.581309902546461e+20 7.0167278463083348e+20 1.9073443887231177e+21 5.1846992652160593e+21 1.4093473476000776e+22 3.831003235981371e+22 1.0413746376682761e+23 2.8307496154307266e+23 7.6947746628514896e+23 2.0916565667371597e+24 5.6857119515524837e+24 1.5455367020327599e+25 4.2012039964445827e+25 1.1420056438012293e+26 3.1042929865047826e+26 8.4383428037470738e+26 2.2937792813113457e+27 6.2351382164292627e+27 + +g: -0.36787945032119751 -0.27067059278488159 -0.14936122298240662 -0.073262564837932587 -0.033689741045236588 -0.014872515574097633 -0.0063831745646893978 -0.0026837014593183994 -0.0011106884339824319 -0.00045399941154755652 -0.00018371877376921475 -7.3730567237362266e-05 -2.9384291337919421e-05 -1.1641405762929935e-05 -4.5885362851549871e-06 -1.8005634956352878e-06 -7.0378973759943619e-07 -2.7413975089984888e-07 -1.0645318582191976e-07 -4.122309249510181e-08 -1.5923385277005764e-08 -6.1368328196920174e-09 -2.3602335641470518e-09 -9.0603280433754207e-10 -3.471987974901225e-10 -1.3283640853956058e-10 -5.0747316071575455e-11 -1.9360334516105304e-11 -7.3766357605586919e-12 -2.8072891233854591e-12 -1.0671687058344537e-12 -4.0525363013271809e-13 -1.5374336461045079e-13 -5.8272932648966574e-14 -2.206792725173521e-14 -8.3502896573240185e-15 -3.1572303958374423e-15 -1.192871523299666e-15 -4.5038112940094517e-16 -1.699343306816689e-16 -6.4078234365689933e-17 -2.4148019279880996e-17 -9.095073346605316e-18 -3.4237017961279004e-18 -1.2881348671140216e-18 -4.8440896082993503e-19 -1.8207810463107454e-19 -6.8407959442757565e-20 -2.569017156788846e-20 -9.6437611040447661e-21 -3.6186962678628536e-21 -1.357346940624028e-21 -5.0894276378983633e-22 -1.9076220526102576e-22 -7.1477077345829229e-23 -2.6773039821769189e-23 -1.0025130740057213e-23 -3.7527418826161672e-24 -1.4043593713279384e-24 -5.2539147015754201e-25 -1.9650207139502987e-25 -7.3474141096711539e-26 -2.7465588329293218e-26 -1.0264406957471058e-26 + + +a: 1.6487212181091309 1.2840254306793213 1.1331484317779541 1.0644944906234741 1.0317434072494507 1.0157476663589478 1.007843017578125 1.0039138793945313 1.0019550323486328 1.0009770393371582 1.0004884004592896 1.000244140625 + +// These are common to both W0 and W-1 +b: 0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125 0.00390625 0.001953125 0.0009765625 0.00048828125 0.000244140625 + +*/ + +// Creates if no file exists, & uses default overwrite/ ios::replace. +//const char filename[] = // "lambert_w_lookup_table.ipp"; // Write to same folder as generator: +//"I:/modular-boost/libs/math/include/boost/math/special_functions/lambert_w_lookup_table.ipp"; +const char filename[] = "lambert_w_lookup_table.ipp"; + +std::ofstream fout(filename, std::ios::out); // File output stream. + +// 128-bit precision type (so that full precision if long double type uses 128-bit). +// typedef cpp_bin_float_quad table_lookup_t; // Output using max_digits10 for 37 decimal digit precision. +// (This is the precision for the tables output as a C++ program, +// not the precision used by the lambert_w.hpp, that defines another typedef lookup_t, default double. + +typedef cpp_bin_float_50 table_lookup_t; // Compute tables to 50 decimla digit precision to avoid slight inaccuracy from repeated multiply. + +// But Output using max_digits10 for 37 decimal digit precision. + +int main() +{ + std::cout << "Lambert W table lookup values." << std::endl; + if (!fout.is_open()) + { // File failed to open OK. + std::cerr << "Open file " << filename << " failed!" << std::endl; + std::cerr << "errno " << errno << std::endl; + return -1; + } + try + { + std::cout << "Lambert W test values writing to file " << filename << std::endl; + int output_precision = std::numeric_limits<cpp_bin_float_quad>::max_digits10; // 37 decimal digits. + fout.precision(output_precision); + fout << + "// Copyright Paul A. Bristow 2017." "\n" + "// Distributed under the Boost Software License, Version 1.0." "\n" + "// (See accompanying file LICENSE_1_0.txt" "\n" + "// or copy at http://www.boost.org/LICENSE_1_0.txt)" "\n" + "\n" + "// " << filename << "\n\n" + "// A collection of 128-bit precision integral z argument Lambert W values computed using " + << output_precision << " decimal digits precision.\n" + "// C++ floating-point precision is 128-bit long double.\n" + "// Output as " + << std::numeric_limits<table_lookup_t>::max_digits10 + << " decimal digits, suffixed L.\n" + "\n" + "// C++ floating-point type is provided by lambert_w.hpp typedef." "\n" + "// For example: typedef lookup_t double; (or float or long double)" "\n" + + "\n" + "// Written by " << __FILE__ << " " << __TIMESTAMP__ << "\n" + << std::endl; + + fout << "// Sizes of arrays of z values for Lambert W[0], W[1] ... W[64]" + "\"n""and W[-1], W[-2] ... W[-64]." << std::endl; + + fout << "\nnamespace boost {\nnamespace math {\nnamespace lambert_w_detail {\nnamespace lambert_w_lookup\n{ \n"; + + BOOST_STATIC_CONSTEXPR std::size_t noof_sqrts = 12; + BOOST_STATIC_CONSTEXPR std::size_t noof_halves = 12; + fout << "BOOST_STATIC_CONSTEXPR std::size_t noof_sqrts = " << noof_sqrts << ";" << std::endl; + fout << "BOOST_STATIC_CONSTEXPR std::size_t noof_halves = " << noof_halves << ";" << std::endl; // Common to both branches. + + BOOST_STATIC_CONSTEXPR std::size_t noof_w0zs = 65; // F[k] 0 <= k <= 64. f[0] = F[0], f[64] = F[64] + BOOST_STATIC_CONSTEXPR std::size_t noof_w0es = 66; // noof_w0zs +1 for gratuitous extra power. + BOOST_STATIC_CONSTEXPR std::size_t noof_wm1zs = 64; // G[k] 1 <= k <= 64. (W-1 = 0 would be z = -infinity, so not stored in array) g[0] == G[1], g[63] = G[64] + BOOST_STATIC_CONSTEXPR std::size_t noof_wm1es = 64; // + + fout << "BOOST_STATIC_CONSTEXPR std::size_t noof_w0es = " << noof_w0zs << ";" << std::endl; + fout << "BOOST_STATIC_CONSTEXPR std::size_t noof_w0zs = " << noof_w0zs << ";" << std::endl; + fout << "BOOST_STATIC_CONSTEXPR std::size_t noof_wm1es = " << noof_wm1zs << ";" << std::endl; + fout << "BOOST_STATIC_CONSTEXPR std::size_t noof_wm1zs = " << noof_wm1zs << ";" << std::endl; + + // Defining actual lookup table sqrts of e^k, e^-k = 1/e, etc. + table_lookup_t halves[noof_halves]; // 0.5 0.25 0.125, 0.0625 ... 0.0002441, halves of previous elements. + table_lookup_t sqrtw0s[noof_sqrts]; // 0.6065 0.7788, 0.8824 ... 0.9997, sqrt of previous elements. + table_lookup_t sqrtwm1s[noof_sqrts]; // 1.6487, 1.2840 1.1331 ... 1.00024 , sqrt of previous elements. + table_lookup_t w0es[noof_w0es]; // lambert_w[k] for W0 branch. 2.7182, 1, 0.3678, 0.1353, ... 1.6038e-28 + table_lookup_t w0zs[noof_w0zs]; // lambert_w[k] for W0 branch. 0. , 2.7182, 14.77, 60.2566 ... 1.445e+29, 3.990e+29. + table_lookup_t wm1es[noof_wm1es]; // lambert_w[k] for W-1 branch. 2.7182 7.38905 20.085 ... 6.235e+27 + table_lookup_t wm1zs[noof_wm1zs]; // lambert_w[k] for W-1 branch. -0.3678 ... -1.0264e-26 + + // e values lambert_w[k] for W-1 branch. 2.7182 1. 0.3678 0.1353 0.04978 ... 4.359e-28 1.603e-28 + + using boost::math::constants::e; + using boost::math::constants::exp_minus_one; + + { // z values for integral W F[k] and powers for W0 branch. + table_lookup_t ej = 1; // + w0es[0] = e<table_lookup_t>(); // e = 2.7182 exp(-1) - 1/e exp_minus_one = 0.36787944. + w0es[1] = 1; // e^0 + w0zs[0] = 0; // F[0] = 0 or W0 branch. + for (int j = 1, jj = 2; jj != noof_w0es; ++jj) + { + w0es[jj] = w0es[j] * exp_minus_one<table_lookup_t>(); // previous * 0.36787944. + ej *= e<table_lookup_t>(); // * 2.7182 + w0zs[j] = j * ej; // For W0 branch. + j = jj; // Previous. + } // for + } + // Checks on accuracy of W0 exponents. + + // Checks on e power w0es + + // w0es[64] = 4.3596100000630809736231248158884615452e-28 + // N[e ^ -63, 37] = 4.359610000063080973623124815888459643*10^-28 + // So slight loss at last decimal place. + + // Checks on accuracy of z for integral W0 w0zs + // w0zs[0] = 0, z = -infinity expected? but = zero + // w0zs[1] = 2.7182818284590452353602874713526623144 + // w0[2] z = 14.778112197861300454460854921150012956 + // w0zs[64] = 3.9904954117194348050619127737142022705e+29 + // N[productlog(0, 3.9904954117194348050619127737142022705 10^+29), 37] + // = 63.99999999999999999999999999999999547 + // = 64.0 to 34 decimal digits, so exact. :-) + + { // z values for integral powers G[k] and e^-k for W-1 branch. + // Fukushima indexing of G (k-1) differs by 1 from(k). + // G[0] = -infinity, so his first item in array g[0] is -0.3678 which is G[1] + // and last is g[63] = G[64] = 1.026e-26 + table_lookup_t e1 = 1. / e<table_lookup_t>(); // 1/e = 0.36787944117144233 + table_lookup_t ej = e1; + wm1es[0] = e<table_lookup_t>(); // e = 2.7182 + wm1zs[0] = -e1; // -1/e = - 0.3678 + for (int j = 0, jj = 1; jj != noof_wm1zs; ++jj) + { + ej *= e1; // * 0.3678.. + wm1es[jj] = wm1es[j] * e<table_lookup_t>(); + wm1zs[jj] = -(jj + 1) * ej; + j = jj; // Previous. + } // for + } + + // Checks on W-1 branch accuracy wm1es by comparing with Wolfram. + // exp powers: + // N[e ^ 1, 37] 2.718281828459045235360287471352662498 + // wm1es[0] = 2.7182818284590452353602874713526623144 - close enough. + // N[e ^ 3, 37] 20.08553692318766774092852965458171790 + // computed wm1es[2] 2.0085536923187667740928529654581712847e+01L OK + // e ^ 66 = 4.6071866343312915426773184428060086893349003037096040 * 10^28 + // N[e ^ 66, 34] = 4.607186634331291542677318442806009 10^28 + // computed 4.6071866343312915426773184428059867859e+28L + // N[e ^ 66, 37] = 4.607186634331291542677318442806008689*10^28 + // so suffering some loss of precision by repeated multiplication computation. + // :-( + + // Repeat with cpp_bin_float_50 and correct to 37th decimal digit. + // 4.60718663433129154267731844280600868933490030370929982 + // output std::cout.precision(std::numeric_limits<cpp_bin_float_quad>::max_digits10) as 37 decimal digits. + // 4.6071866343312915426773184428060086893e+28L + // N[e ^ 66, 37] = 4.607186634331291542677318442806008689*10^28 + // Agrees exactly for 37th place, so should be read in to nearest representable value. + + + // Checks W-1 branch z values wm1zs + // W-1[0] = -2.7067056647322538378799898994496883858e-01 + // w-1[1] = -1.4936120510359182893802724695018536337e-01 + + // wm1zs[65] -1.4325445274604020119111357113179868158e-27 + + // N[productlog(-1, -1.4325445274604020119111357113179868158* 10^-27), 37] + // = -65.99999999999999999999999999999999955 + // = -66 accurately, so this is OK. + // z = 66 * e^66 = + // =N[-66*e ^ -66, 37] + // -1.432544527460402011911135711317986177*10^-27 + // wm1zs[65] -1.4325445274604020119111357113179868158e-27 + // which agrees well enough to 34 decimal digits. + // last wm1zs[65] = 0 is unused. + + // Halves, common to both W0 and W-1. + halves[0] = static_cast<table_lookup_t>(0.5); // Exactly representable. + for (int j = 0; j != noof_sqrts -1; ++j) + { + halves[j+1] = halves[j] / 2; // Half previous element (/2 will be optimised better?). + } // for j + + // W0 sqrts + sqrtw0s[0] = static_cast<table_lookup_t>(0.606530659712633423603799534991180453441918135487186955682L); + for (int j = 0; j != noof_sqrts -1; ++j) + { + sqrtw0s[j+1] = sqrt(sqrtw0s[j]); // Sqrt of previous element. sqrt(1/e), sqrt(sqrt(1/e)) ... + } // for j + + // W-1 sqrts + sqrtwm1s[0] = root_e<table_lookup_t>(); + for (int j = 0; j != noof_sqrts -1; ++j) + { + sqrtwm1s[j+1] = sqrt(sqrtwm1s[j]); // Sqrt of previous element. sqrt(1/e), sqrt(sqrt(1/e)) ... + } // for j + + // Output values as C++ arrays, + // using BOOST_STATIC_CONSTEXPR as static and constexpr as possible for platform. + fout << std::noshowpoint; // Do show NOT trailing zeros for halves and sqrts values. + + fout << + "\n" "BOOST_STATIC_CONSTEXPR lookup_t halves[noof_halves] = " // + "\n" "{ // Common to Lambert W0 and W-1 (and exactly representable)." << "\n "; + for (int i = 0; i != noof_halves; i++) + { + fout << halves[i] << 'L'; + if (i != noof_halves - 1) + { // Omit trailing comma on last element. + fout << ", "; + } + else + { + fout << std::endl; + } + } + fout << "}; // halves, 0.5, 0.25, ... 0.000244140625, common to W0 and W-1." << std::endl; + + fout << + "\n" "BOOST_STATIC_CONSTEXPR lookup_t sqrtw0s[noof_sqrts] = " // + "\n" "{ // For Lambert W0 only." << "\n "; + for (int i = 0; i != noof_sqrts; i++) + { + fout << sqrtw0s[i] << 'L'; + if (i != noof_sqrts - 1) + { // Omit trailing comma on last element. + fout << ", "; + } + else + { + fout << std::endl; + } + } + fout << "}; // sqrtw0s" << std::endl; + + fout << + "\n" "BOOST_STATIC_CONSTEXPR lookup_t sqrtwm1s[noof_sqrts] = " // + "\n" "{ // For Lambert W-1 only." << "\n "; + for (int i = 0; i != noof_sqrts; i++) + { + fout << sqrtwm1s[i] << 'L'; + if (i != noof_sqrts - 1) + { // Omit trailing comma on last element. + fout << ", "; + } + else + { + fout << std::endl; + } + } + fout << "}; // sqrtwm1s" << std::endl; + + fout << std::scientific // May be needed to avoid very large dddddddddddddddd.ddddddddddddddd output? + << std::showpoint; // Do show trailing zeros for sqrts and halves. + + // Two W0 arrays + + fout << // W0 e values. + // Fukushima code generates an extra unused power, but it is not output by using noof_w0zs instead of noof_w0es. + "\n" "BOOST_STATIC_CONSTEXPR lookup_t w0es[noof_w0zs] = " // + "\n" "{ // Fukushima e powers array e[0] = 2.718, 1., e[2] = e^-1 = 0.135, e[3] = e^-2 = 0.133 ... e[64] = 4.3596100000630809736231248158884615452e-28." << "\n "; + for (int i = 0; i != noof_w0zs; i++) + { + fout << w0es[i] << 'L'; + if (i != noof_w0es - 1) + { // Omit trailing comma on last element. + fout << ", "; + } + if (i % 4 == 0) + { + fout << "\n "; + } + } + fout << "\n}; // w0es" << std::endl; + + fout << // W0 z values for W[1], . + "\n" "BOOST_STATIC_CONSTEXPR lookup_t w0zs[noof_w0zs] = " // + "\n" "{ // z values for W[0], W[1], W[2] ... W[64] (Fukushima array Fk). " << "\n "; + for (int i = 0; i != noof_w0zs; i++) + { + fout << w0zs[i] << 'L'; + if (i != noof_w0zs - 1) + { // Omit trailing comma on last element. + fout << ", "; + } + if (i % 4 == 0) + { + fout << "\n "; + } + } + fout << "\n}; // w0zs" << std::endl; + + // Two arrays for w-1 + + fout << // W-1 e values. + "\n" "BOOST_STATIC_CONSTEXPR lookup_t wm1es[noof_wm1es] = " // + "\n" "{ // Fukushima e array e[0] = e^1 = 2.718, e[1] = e^2 = 7.39 ... e[64] = 4.60718e+28." << "\n "; + for (int i = 0; i != noof_wm1es; i++) + { + fout << wm1es[i] << 'L'; + if (i != noof_wm1es - 1) + { // Omit trailing comma on last element. + fout << ", "; + } + if (i % 4 == 0) + { + fout << "\n "; + } + } + fout << "\n}; // wm1es" << std::endl; + + fout << // Wm1 z values for integral K. + "\n" "BOOST_STATIC_CONSTEXPR lookup_t wm1zs[noof_wm1zs] = " // + "\n" "{ // Fukushima G array of z values for integral K, (Fukushima Gk) g[0] (k = -1) = 1 ... g[64] = -1.0264389699511303e-26." << "\n "; + for (int i = 0; i != noof_wm1zs; i++) + { + fout << wm1zs[i] << 'L'; + if (i != noof_wm1zs - 1) + { // Omit trailing comma on last element. + fout << ", "; + } + if (i % 4 == 0) + { // 4 values per line. + fout << "\n "; + } + } + fout << "\n}; // wm1zs" << std::endl; + + fout << "} // namespace lambert_w_lookup\n} // namespace lambert_w_detail\n} // namespace math\n} // namespace boost" << std::endl; + } + catch (std::exception& ex) + { + std::cout << "Exception " << ex.what() << std::endl; + } + fout.close(); + return 0; + +} // int main() + +/* + +Original arrays as output by Veberic/Fukushima code: + +w0 branch + +W-1 branch + +e: 2.7182818284590451 7.3890560989306495 20.085536923187664 54.598150033144229 148.41315910257657 403.42879349273500 1096.6331584284583 2980.9579870417274 8103.0839275753815 22026.465794806707 59874.141715197788 162754.79141900383 442413.39200892020 1202604.2841647759 3269017.3724721079 8886110.5205078647 24154952.753575277 65659969.137330450 178482300.96318710 485165195.40978980 1318815734.4832134 3584912846.1315880 9744803446.2488918 26489122129.843441 72004899337.385788 195729609428.83853 532048240601.79797 1446257064291.4734 3931334297144.0371 10686474581524.447 29048849665247.383 78962960182680.578 214643579785915.75 583461742527454.00 1586013452313428.3 4311231547115188.5 11719142372802592. 31855931757113704. 86593400423993600. 2.3538526683701958e+17 6.3984349353005389e+17 1.7392749415204982e+18 4.7278394682293381e+18 1.2851600114359284e+19 3.4934271057485025e+19 9.4961194206024286e+19 2.5813128861900616e+20 7.0167359120976157e+20 1.9073465724950953e+21 5.1847055285870605e+21 1.4093490824269355e+22 3.8310080007165677e+22 1.0413759433029062e+23 2.8307533032746866e+23 7.6947852651419974e+23 2.0916594960129907e+24 5.6857199993359170e+24 1.5455389355900996e+25 4.2012104037905024e+25 1.1420073898156810e+26 3.1042979357019109e+26 8.4383566687414291e+26 2.2937831594696028e+27 6.2351490808115970e+27 + +g: -0.36787944117144233 -0.27067056647322540 -0.14936120510359185 -0.073262555554936742 -0.033689734995427351 -0.014872513059998156 -0.0063831737588816162 -0.0026837010232200957 -0.0011106882367801162 -0.00045399929762484866 -0.00018371870869270232 -7.3730548239938541e-05 -2.9384282290753722e-05 -1.1641402067449956e-05 -4.5885348075273889e-06 -1.8005627955081467e-06 -7.0378941219347870e-07 -2.7413963540482742e-07 -1.0645313231320814e-07 -4.1223072448771179e-08 -1.5923376898615014e-08 -6.1368298043116385e-09 -2.3602323152914367e-09 -9.0603229062698418e-10 -3.4719859662410078e-10 -1.3283631472964657e-10 -5.0747278046555293e-11 -1.9360320299432585e-11 -7.3766303773930841e-12 -2.8072868906520550e-12 -1.0671679036256938e-12 -4.0525329757101402e-13 -1.5374324278841227e-13 -5.8272886672428505e-14 -2.2067908660514491e-14 -8.3502821888768594e-15 -3.1572276215253082e-15 -1.1928704609782527e-15 -4.5038074274761624e-16 -1.6993417021166378e-16 -6.4078169762734621e-17 -2.4147993510032983e-17 -9.0950634616416589e-18 -3.4236981860988753e-18 -1.2881333612472291e-18 -4.8440839844747606e-19 -1.8207788854829806e-19 -6.8407875971564987e-20 -2.5690139750481013e-20 -9.6437492398196038e-21 -3.6186918227652047e-21 -1.3573451162272088e-21 -5.0894204288896066e-22 -1.9076194289884390e-22 -7.1476978375412793e-23 -2.6773000149758669e-23 -1.0025115553818592e-23 -3.7527362568743735e-24 -1.4043571811296988e-24 -5.2539064576179218e-25 -1.9650175744554385e-25 -7.3474021582506962e-26 -2.7465543000397468e-26 -1.0264389699511303e-26 + +a: 1.6487212707001282 1.2840254166877414 1.1331484530668263 1.0644944589178595 1.0317434074991028 1.0157477085866857 1.0078430972064480 1.0039138893383477 1.0019550335910028 1.0009770394924165 1.0004884004786945 1.0002441704297478 + +b: 0.50000000000000000 0.25000000000000000 0.12500000000000000 0.062500000000000000 0.031250000000000000 0.015625000000000000 0.0078125000000000000 0.0039062500000000000 0.0019531250000000000 0.00097656250000000000 0.00048828125000000000 0.00024414062500000000 + + +*/ + + diff --git a/src/boost/libs/math/tools/lambert_w_low_reference_values.cpp b/src/boost/libs/math/tools/lambert_w_low_reference_values.cpp new file mode 100644 index 00000000..177c6500 --- /dev/null +++ b/src/boost/libs/math/tools/lambert_w_low_reference_values.cpp @@ -0,0 +1,237 @@ +// lambert_w_test_values.cpp + +// Copyright Paul A. Bristow 2017. +// 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) + +// Write a C++ file J:\Cpp\Misc\lambert_w_1000_test_values\lambert_w_mp_values.ipp +// containing arrays of z arguments and 100 decimal digit precision lambert_w0(z) reference values. +// These can be used in tests of precision of less-precise types like +// built-in float, double, long double and quad and cpp_dec_float_50. + +// Multiprecision types: +//#include <boost/multiprecision/cpp_bin_float.hpp> +#include <boost/multiprecision/cpp_dec_float.hpp> // boost::multiprecision::cpp_dec_float_100 +using boost::multiprecision::cpp_dec_float_100; + +#include <boost/math/special_functions/lambert_w.hpp> // +using boost::math::lambert_w0; + +#include <iostream> +// using std::cout; using std::std::endl; using std::ios; using std::std::cerr; +#include <iomanip> +using std::setprecision; +using std::showpoint; +#include <fstream> +using std::ofstream; +#include <cassert> +#include <cfloat> // for DBL_EPS etc +#include <limits> // for numeric limits. +//#include <ctype> +#include <string> +#include <algorithm> +using std::transform; + +const char* prefix = "static "; // "static const" or "static constexpr" or just "const "" or "" even? +// But problems with VS2017 and GCC not accepting same format mean only static at present. + +const long double eps = std::numeric_limits<long double>::epsilon(); + +/* + +// Sample test values from Wolfram. +template <typename RealType> +static RealType zs[noof_tests]; + +template <typename RealType> +void init_zs() +{ + zs<RealType>[0] = BOOST_MATH_TEST_VALUE(RealType, -0.35); + zs<RealType>[1] = BOOST_MATH_TEST_VALUE(RealType, -0.3); + zs<RealType>[2] = BOOST_MATH_TEST_VALUE(RealType, -0.01); + zs<RealType>[3] = BOOST_MATH_TEST_VALUE(RealType, +0.01); + zs<RealType>[4] = BOOST_MATH_TEST_VALUE(RealType, 0.1); + zs<RealType>[5] = BOOST_MATH_TEST_VALUE(RealType, 0.5); + zs<RealType>[6] = BOOST_MATH_TEST_VALUE(RealType, 1.); + zs<RealType>[7] = BOOST_MATH_TEST_VALUE(RealType, 2.); + zs<RealType>[8] = BOOST_MATH_TEST_VALUE(RealType, 5.); + zs<RealType>[9] = BOOST_MATH_TEST_VALUE(RealType, 10.); + zs<RealType>[10] = BOOST_MATH_TEST_VALUE(RealType, 100.); + zs<RealType>[11] = BOOST_MATH_TEST_VALUE(RealType, 1e+6); +}; + +// 'Known good' Lambert w values using N[productlog(-0.3), 50] +// evaluated to full precision of RealType (up to 50 decimal digits). +template <typename RealType> +static RealType ws[noof_tests]; + +template <typename RealType> +void init_ws() +{ + ws<RealType>[0] = BOOST_MATH_TEST_VALUE(RealType, -0.7166388164560738505881698000038650406110575701385055261614344530078353170171071547711151137001759321); + ws<RealType>[1] = BOOST_MATH_TEST_VALUE(RealType, -0.4894022271802149690362312519962933689234100060163590345114659679736814083816206187318524147462752111); + ws<RealType>[2] = BOOST_MATH_TEST_VALUE(RealType, -0.01010152719853875327292018767138623973670903993475235877290726369225412969738704722202330440072213641); + ws<RealType>[3] = BOOST_MATH_TEST_VALUE(RealType, 0.009901473843595011885336326816570107953627746494917415482611387085655068978243229360100010886171970918); + ws<RealType>[4] = BOOST_MATH_TEST_VALUE(RealType, 0.09127652716086226429989572142317956865311922405147203264830839460717224625441755165020664592995606710); + ws<RealType>[5] = BOOST_MATH_TEST_VALUE(RealType, 0.3517337112491958260249093009299510651714642155171118040466438461099606107203387108968323038321915693); + ws<RealType>[6] = BOOST_MATH_TEST_VALUE(RealType, 0.5671432904097838729999686622103555497538157871865125081351310792230457930866845666932194469617522946); // Output from https://www.wolframalpha.com/input/?i=lambert_w0(1) + ws<RealType>[7] = BOOST_MATH_TEST_VALUE(RealType, 0.8526055020137254913464724146953174668984533001514035087721073946525150656742630448965773783502494847); + ws<RealType>[8] = BOOST_MATH_TEST_VALUE(RealType, 1.326724665242200223635099297758079660128793554638047479789290393025342679920536226774469916608426789); // https://www.wolframalpha.com/input/?i=N%5Bproductlog(5),+100%5D + ws<RealType>[9] = BOOST_MATH_TEST_VALUE(RealType, 1.745528002740699383074301264875389911535288129080941331322206048555557259941551704989523510778883075); + ws<RealType>[10] = BOOST_MATH_TEST_VALUE(RealType, 3.385630140290050184888244364529726867491694170157806680386174654885206544913039277686735236213650781); + ws<RealType>[11] = BOOST_MATH_TEST_VALUE(RealType, 11.38335808614005262200015678158500428903377470601886512143238610626898610768018867797709315493717650); + ////W(1e35) = 76.256377207295812974093508663841808129811690961764 too big for float. +}; + +*/ + +// Global so accessible from output_value. +// Creates if no file exists, & uses default overwrite/ ios::replace. +const char filename[] = "lambert_w_low_reference values.ipp"; // +std::ofstream fout(filename, std::ios::out); ; // + +// 100 decimal digits for the value fed to macro BOOST_MATH_TEST_VALUE +typedef cpp_dec_float_100 RealType; + +void output_value(size_t index, RealType value) +{ + fout + << " zs<RealType>[" << index << "] = BOOST_MATH_TEST_VALUE(RealType, " + << value + << ");" + << std::endl; + return; +} + +void output_lambert_w0(size_t index, RealType value) +{ + fout + << " ws<RealType>[" << index << "] = BOOST_MATH_TEST_VALUE(RealType, " + << lambert_w0(value) + << ");" + << std::endl; + return; +} + +int main() +{ // Make C++ file containing Lambert W test values. + std::cout << filename << " "; +#ifdef __TIMESTAMP__ + std::cout << __TIMESTAMP__; +#endif + std::cout << std::endl; + std::cout << "Lambert W0 decimal digit precision values." << std::endl; + + // Note __FILE__ & __TIMESTAMP__ are ANSI standard C & thus Std C++? + + if (!fout.is_open()) + { // File failed to open OK. + std::cerr << "Open file " << filename << " failed!" << std::endl; + std::cerr << "errno " << errno << std::endl; + return -1; + } + + int output_precision = std::numeric_limits<cpp_dec_float_100>::digits10; + // cpp_dec_float_100 is ample precision and + // has several extra bits internally so max_digits10 are not needed. + fout.precision(output_precision); + + int no_of_tests = 100; + + // Intro for RealType values. + std::cout << "Lambert W test values written to file " << filename << std::endl; + fout << + "\n" + "// A collection of Lambert W test values computed using " + << output_precision << " decimal digits precision.\n" + "// C++ floating-point type is " << "RealType." "\n" + "\n" + "// Written by " << __FILE__ << " " << __TIMESTAMP__ << "\n" + + "\n" + "// Copyright Paul A. Bristow 2017." "\n" + "// Distributed under the Boost Software License, Version 1.0." "\n" + "// (See accompanying file LICENSE_1_0.txt" "\n" + "// or copy at http://www.boost.org/LICENSE_1_0.txt)" "\n" + << std::endl; + + fout << "// Size of arrays of arguments z and Lambert W" << std::endl; + fout << "static const unsigned int noof_tests = " << no_of_tests << ";" << std::endl; + + // Declare arrays of z and Lambert W. + + fout << "// Declare arrays of arguments z and Lambert W(z)" << std::endl; + fout << "// The values are defined using the macro BOOST_MATH_TEST_VALUE to ensure\n" + "// that both built-in and multiprecision types are correctly initialiased with full precision.\n" + "// built-in types like double require a floating-point literal like 3.14,\n" + "// but multiprecision types require a decimal digit string like \"3.14\".\n" + << std::endl; + fout << + "\n" + "template <typename RealType>""\n" + "static RealType zs[" << no_of_tests << "];" + << std::endl; + + fout << + "\n" + "template <typename RealType>""\n" + "static RealType ws[" << no_of_tests << "];" + << std::endl; + + RealType max_z("10"); + RealType min_z("-0.35"); + RealType step_size("0.01"); + size_t step_count = no_of_tests; + + // Output to initialize array of arguments z for Lambert W. + fout << + "\n" + << "template <typename RealType>\n" + "void init_zs()\n" + "{\n"; + + RealType z = min_z; + for (size_t i = 0; (i < no_of_tests); i++) + { + output_value(i, z); + z += step_size; + } + fout << "};" << std::endl; + + // Output array of Lambert W values. + fout << + "\n" + << "template <typename RealType>\n" + "void init_ws()\n" + "{\n"; + + z = min_z; + for (size_t i = 0; (i < step_count); i++) + { + output_lambert_w0(i, z); + z += step_size; + } + fout << "};" << std::endl; + + fout << "// End of lambert_w_mp_values.ipp " << std::endl; + fout.close(); + + std::cout << "Lambert_w0 values written to files " << __TIMESTAMP__ << std::endl; + return 0; +} // main + + +/* + +start and finish checks again Wolfram Alpha: +ws<RealType>[0] = BOOST_MATH_TEST_VALUE(RealType, -0.7166388164560738505881698000038650406110575701385055261614344530078353170171071547711151137001759321); +Wolfram N[productlog(-0.35), 100] -0.7166388164560738505881698000038650406110575701385055261614344530078353170171071547711151137001759321 + + +ws<RealType>[19] = BOOST_MATH_TEST_VALUE(RealType, 0.7397278549447991214587608743391115983469848985053641692586810406118264600667862543570373167046626221); +Wolfram N[productlog(1.55), 100] 0.7397278549447991214587608743391115983469848985053641692586810406118264600667862543570373167046626221 + + +*/ + diff --git a/src/boost/libs/math/tools/lanczos_generator.cpp b/src/boost/libs/math/tools/lanczos_generator.cpp new file mode 100644 index 00000000..a16d4364 --- /dev/null +++ b/src/boost/libs/math/tools/lanczos_generator.cpp @@ -0,0 +1,5198 @@ +// (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 <boost/math/constants/constants.hpp> +#include <boost/math/tools/precision.hpp> +#include <boost/math/tools/polynomial.hpp> +#include <boost/numeric/ublas/matrix.hpp> +#include <boost/numeric/ublas/io.hpp> +#include <boost/numeric/ublas/operation.hpp> +#include <boost/cstdint.hpp> +#include <boost/bind.hpp> +#include <boost/math/special_functions/log1p.hpp> +#include <boost/math/special_functions/relative_difference.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/array.hpp> +#include <boost/random.hpp> +#include <boost/chrono.hpp> +#include "mp_t.hpp" + +// +// Define MP_TYPE +// to a specific precision multiprecision type if you want to +// create a lanczos approximation for that type. +// + +#define MP_TYPE boost::multiprecision::number<boost::multiprecision::cpp_bin_float<100> > + +// +// this is a sort of recursive include, since this file +// is used to create the contents of gamma.hpp. +// However, we will be using the "generic" version of gamma +// which doesn't use a lanczos approximation. +// +#include <boost/math/special_functions/gamma.hpp> + +#include <iostream> +#include <iomanip> +#include <vector> + +using boost::numeric::ublas::matrix; +using boost::numeric::ublas::vector; + +struct lanczos_spot_data +{ + int N; + double g; + double err; +}; + +lanczos_spot_data sweet_spots[] = { +// a few selected spots from Pugh's thesis: +3, 2.03209, 6.4e-7, +4, 3.655180, 8.5e-8, +9, 8.406094, 6.9e-15, +10, 9.656578, 2.1e-16, +11, 10.900511, 6.1e-18, +12, 12.066012, 1.1e-19, +13, 13.144565, 5.2e-21, +14, 13.726821, 4.0e-22, +15, 14.977863, 1.2e-23, +20, 20.298892, 7.8e-31, +21, 21.508926, 2.1e-32, +22, 22.618910, 1.8e-34, +23, 23.118012, 5.2e-35, + +// some more we've found, these are all the points where the first +// negleted term from the Lanczos series changes sign, there is one +// point just above that point, and one just below: + +3, 0.58613894134759903, 0.00036580426080686315, +3, 0.58613894879817963, 0.00036580416320668711, +3, 1.249951496720314, 4.2305536798953929e-005, +3, 1.2499515041708946, 4.2305534015367749e-005, +3, 1.8384982049465179, 1.164778449938813e-005, +3, 1.8384982123970985, 1.1647786529958048e-005, +3, 2.3276706635951996, 5.3732582230468998e-006, +3, 2.3276706710457802, 5.3732600294516588e-006, +3, 2.6038404405117035, 7.4060771171390379e-007, +3, 2.6038404479622841, 7.406058543248471e-007, +4, 0.62704569846391678, 0.00012800533557793425, +4, 0.62704570591449738, 0.00012800531551557324, +4, 1.3344274088740349, 9.0166140418663663e-006, +4, 1.3344274163246155, 9.0166116338646694e-006, +4, 1.9880444705486298, 1.4955557778725745e-006, +4, 1.9880444779992104, 1.4955557079994109e-006, +4, 2.5835030898451805, 4.5877676859600527e-007, +4, 2.5835030972957611, 4.5877667876325684e-007, +4, 3.1086832508444786, 2.1441725587707906e-007, +4, 3.1086832582950592, 2.1441723688775765e-007, +4, 3.5476611852645874, 1.0813760990515544e-007, +4, 3.547661192715168, 1.0813766234070327e-007, +4, 3.6492579728364944, 1.047642251124206e-007, +4, 3.649257980287075, 1.0476415796074403e-007, +5, 0.65435918420553207, 5.5274429026631278e-005, +5, 0.65435919165611267, 5.527441185903385e-005, +5, 1.389187254011631, 2.6307833416554052e-006, +5, 1.3891872614622116, 2.6307826816540255e-006, +5, 2.0801975876092911, 2.9014694764756466e-007, +5, 2.0801975950598717, 2.9014696142909125e-007, +5, 2.7272208333015442, 5.9176544536206063e-008, +5, 2.7272208407521248, 5.9176528019009275e-008, +5, 3.3269794136285782, 1.9379184595472579e-008, +5, 3.3269794210791588, 1.9379189057179851e-008, +5, 3.8722873777151108, 9.0123694745032944e-009, +5, 3.8722873851656914, 9.0123661007867372e-009, +5, 4.3516943231225014, 4.9816097608842378e-009, +5, 4.351694330573082, 4.9816087871575021e-009, +6, 0.67425807565450668, 2.7371903086326379e-005, +6, 0.67425808310508728, 2.7371893712684938e-005, +6, 1.4284561350941658, 9.4138428977455083e-007, +6, 1.4284561425447464, 9.4138417896969612e-007, +6, 2.1447814926505089, 7.4109049995920916e-008, +6, 2.1447815001010895, 7.4109044064461768e-008, +6, 2.8244904428720474, 1.0708333024058614e-008, +6, 2.824490450322628, 1.0708333661155651e-008, +6, 3.4669468700885773, 2.4940116660002578e-009, +6, 3.4669468775391579, 2.4940118560592828e-009, +6, 4.0696377158164978, 8.5267622527507512e-010, +6, 4.0696377232670784, 8.5267624048985822e-010, +6, 4.6278460025787354, 3.9323405231792876e-010, +6, 4.6278460100293159, 3.9323393550021793e-010, +6, 5.1345816180109978, 2.1943462473419721e-010, +6, 5.1345816254615784, 2.1943458105218707e-010, +6, 5.5917193591594696, 1.242916896389048e-010, +6, 5.5917193666100502, 1.2429175679293363e-010, +7, 0.68959406018257141, 1.4934177419305624e-005, +7, 0.68959406763315201, 1.4934171696393048e-005, +7, 1.4584139510989189, 3.8891482410396904e-007, +7, 1.4584139585494995, 3.8891475436265016e-007, +7, 2.1934122517704964, 2.2977989848570384e-008, +7, 2.193412259221077, 2.2977982819591052e-008, +7, 2.8964230641722679, 2.4742239281355561e-009, +7, 2.8964230716228485, 2.4742234478616864e-009, +7, 3.5678729563951492, 4.2816138965285379e-010, +7, 3.5678729638457298, 4.2816128067858218e-010, +7, 4.2069913893938065, 1.0931003472338519e-010, +7, 4.2069913968443871, 1.0931004659777642e-010, +7, 4.8118086308240891, 3.8518213120095777e-011, +7, 4.8118086382746696, 3.8518212172324096e-011, +7, 5.3790060579776764, 1.7613602961109952e-011, +7, 5.379006065428257, 1.7613603275796266e-011, +7, 5.9039439857006073, 9.7098281187573355e-012, +7, 5.9039439931511879, 9.7098271522398387e-012, +7, 6.3838147521018982, 5.7878801570305524e-012, +7, 6.3838147595524788, 5.7878771973838702e-012, +7, 6.7833591029047966, 2.829092368392454e-012, +7, 6.7833591103553772, 2.8290901754246269e-012, +8, 0.70188850909471512, 8.7610752024780369e-006, +8, 0.70188851654529572, 8.7610704217796693e-006, +8, 1.4822541922330856, 1.7881701068328982e-007, +8, 1.4822541996836662, 1.7881694190606741e-007, +8, 2.231784276664257, 8.2272386690167009e-009, +8, 2.2317842841148376, 8.2272367814664617e-009, +8, 2.9525627419352531, 6.8591536474980462e-010, +8, 2.9525627493858337, 6.8591515664364383e-010, +8, 3.6455128863453865, 9.1549235855884194e-011, +8, 3.6455128937959671, 9.1549217088498416e-011, +8, 4.3106606528162956, 1.8015466799942756e-011, +8, 4.3106606602668762, 1.8015467001952356e-011, +8, 4.9472371935844421, 4.918149362493385e-012, +8, 4.9472372010350227, 4.9181495178774722e-012, +8, 5.553666315972805, 1.7720036810370511e-012, +8, 5.5536663234233856, 1.7720035779693502e-012, +8, 6.1274929493665695, 8.0403304333886761e-013, +8, 6.1274929568171501, 8.0403274526493467e-013, +8, 6.6654317826032639, 4.3551924163930176e-013, +8, 6.6654317900538445, 4.3551918580885179e-013, +8, 7.1646013185381889, 2.6142608803934048e-013, +8, 7.1646013259887695, 2.6142610866873453e-013, +8, 7.6312204822897911, 1.5767278184484503e-013, +8, 7.6312204897403717, 1.576728292094547e-013, +8, 7.8779716044664383, 6.0579161144149095e-014, +8, 7.8779716119170189, 6.0579145495868576e-014, +9, 0.7120363786816597, 5.4383680639900953e-006, +9, 0.7120363861322403, 5.4383647430909934e-006, +9, 1.5018193200230598, 8.9331552269793478e-008, +9, 1.5018193274736404, 8.9331529217486569e-008, +9, 2.2630845010280609, 3.2922940247769628e-009, +9, 2.2630845084786415, 3.2922936681951672e-009, +9, 2.9980199560523033, 2.1887825488935961e-010, +9, 2.9980199635028839, 2.1887818854849753e-010, +9, 3.7078000977635384, 2.3213138957857667e-011, +9, 3.707800105214119, 2.3213132917173771e-011, +9, 4.3928612694144249, 3.6226509291513855e-012, +9, 4.3928612768650055, 3.6226507116549233e-012, +9, 5.0530400574207306, 7.8472620106742312e-013, +9, 5.0530400648713112, 7.8472599177745781e-013, +9, 5.6876183524727821, 2.2542091218064693e-013, +9, 5.6876183599233627, 2.2542085472082343e-013, +9, 6.2953110262751579, 8.261026286619692e-014, +9, 6.2953110337257385, 8.2610267677539022e-014, +9, 6.8742315545678139, 3.7226229880661886e-014, +9, 6.8742315620183945, 3.722621661830273e-014, +9, 7.4219388365745544, 1.9804198141916339e-014, +9, 7.421938844025135, 1.9804197841080089e-014, +9, 7.936030775308609, 1.1800366216622659e-014, +9, 7.9360307827591896, 1.1800362381207757e-014, +9, 8.4175376817584038, 7.341772297716249e-015, +9, 8.4175376892089844, 7.3417744970482286e-015, +10, 0.72060277312994003, 3.5324438420494327e-006, +10, 0.72060278058052063, 3.5324425213780505e-006, +10, 1.5182576552033424, 4.7690979892410133e-008, +10, 1.518257662653923, 4.7690968887170632e-008, +10, 2.2892609387636185, 1.4396365431590603e-009, +10, 2.2892609462141991, 1.4396363283470758e-009, +10, 3.0358340814709663, 7.8118059457005561e-011, +10, 3.0358340889215469, 7.8118048721726738e-011, +10, 3.7592824399471283, 6.7417155809106958e-012, +10, 3.7592824473977089, 6.7417147580480395e-012, +10, 4.4602697342634201, 8.5434024476488055e-013, +10, 4.4602697417140007, 8.5434000006256964e-013, +10, 5.1389683187007904, 1.5015237157428729e-013, +10, 5.138968326151371, 1.5015232503714518e-013, +10, 5.795127771794796, 3.5035278065891386e-014, +10, 5.7951277792453766, 3.5035266685032581e-014, +10, 6.4280949085950851, 1.0474518584578706e-014, +10, 6.4280949160456657, 1.047451900091486e-014, +10, 7.0368044599890709, 3.8902615249132166e-015, +10, 7.0368044674396515, 3.8902605386615012e-015, +10, 7.6197631657123566, 1.742442940023884e-015, +10, 7.6197631731629372, 1.7424426824540998e-015, +10, 8.1750892177224159, 9.1144555287546294e-016, +10, 8.1750892251729965, 9.1144560389833963e-016, +10, 8.7008367404341698, 5.3541847847332351e-016, +10, 8.7008367478847504, 5.3541844723127514e-016, +10, 9.1965094059705734, 3.3560389199894529e-016, +10, 9.196509413421154, 3.3560370421140035e-016, +10, 9.6678015515208244, 2.1059571242602905e-016, +10, 9.667801558971405, 2.1059579862533338e-016, +11, 0.72796426713466644, 2.3816013324880167e-006, +11, 0.72796427458524704, 2.3816003939892356e-006, +11, 1.5323273167014122, 2.6884539057733283e-008, +11, 1.5323273241519928, 2.6884532967611841e-008, +11, 2.3115825653076172, 6.7682186491374862e-010, +11, 2.3115825727581978, 6.768217495558193e-010, +11, 3.0679489448666573, 3.0544688315708309e-011, +11, 3.0679489523172379, 3.054468452617125e-011, +11, 3.8027990683913231, 2.186949692679853e-012, +11, 3.8027990758419037, 2.1869496552307528e-012, +11, 4.5169280469417572, 2.2947351040888336e-013, +11, 4.5169280543923378, 2.2947348773371414e-013, +11, 5.2107065990567207, 3.3353640359739479e-014, +11, 5.2107066065073013, 3.335363154144172e-014, +11, 5.8841593414545059, 6.4351159890193404e-015, +11, 5.8841593489050865, 6.435115249418266e-015, +11, 6.5370001494884491, 1.5930548620019077e-015, +11, 6.5370001569390297, 1.59305482454352e-015, +11, 7.1686412021517754, 4.9183710858836462e-016, +11, 7.168641209602356, 4.9183713116224844e-016, +11, 7.7781866490840912, 1.8464804238726119e-016, +11, 7.7781866565346718, 1.8464801709489452e-016, +11, 8.3644260391592979, 8.2263320775918765e-017, +11, 8.3644260466098785, 8.2263297787354186e-017, +11, 8.9258662387728691, 4.2375346461043962e-017, +11, 8.9258662462234497, 4.2375329267920249e-017, +11, 9.4609249979257584, 2.4482616150935944e-017, +11, 9.460925005376339, 2.4482619419420328e-017, +11, 9.968697115778923, 1.5254006021629585e-017, +11, 9.9686971232295036, 1.5254009931381535e-017, +11, 10.451380550861359, 9.7234265908062383e-018, +11, 10.451380558311939, 9.7234241296957717e-018, +11, 10.909898526966572, 6.3147967493977272e-018, +11, 10.909898534417152, 6.3147961332742783e-018, +12, 0.73438271880149841, 1.6566052109275983e-006, +12, 0.73438272625207901, 1.6566045155548952e-006, +12, 1.5445517003536224, 1.5860666784152459e-008, +12, 1.544551707804203, 1.5860658867525684e-008, +12, 2.33091701567173, 3.380059232629492e-010, +12, 2.3309170231223106, 3.3800585031437757e-010, +12, 3.095676377415657, 1.2884951580384992e-011, +12, 3.0956763848662376, 1.2884947453406877e-011, +12, 3.8402339816093445, 7.7768150022424858e-013, +12, 3.8402339890599251, 7.776814490345326e-013, +12, 4.5654622465372086, 6.8670097741098332e-014, +12, 4.5654622539877892, 6.8670083429297199e-014, +12, 5.2718541026115417, 8.38897478481124e-015, +12, 5.2718541100621223, 8.3889742372884196e-015, +12, 5.9596048966050148, 1.3595098759195538e-015, +12, 5.9596049040555954, 1.3595098086325987e-015, +12, 6.6286550611257553, 2.827608125932321e-016, +12, 6.6286550685763359, 2.8276074709416868e-016, +12, 7.2787091657519341, 7.3455425966950088e-017, +12, 7.2787091732025146, 7.3455407058460195e-017, +12, 7.9092400223016739, 2.3285371485286439e-017, +12, 7.9092400297522545, 2.3285373002934362e-017, +12, 8.5194846615195274, 8.8196897130872609e-018, +12, 8.519484668970108, 8.8196870510698361e-018, +12, 9.1084426045417786, 3.9108299199270105e-018, +12, 9.1084426119923592, 3.9108294386613317e-018, +12, 9.6749012768268585, 1.9869557945423399e-018, +12, 9.6749012842774391, 1.9869552330025425e-018, +12, 10.217559166252613, 1.1287442348688164e-018, +12, 10.217559173703194, 1.1287443889939456e-018, +12, 10.735452570021152, 6.9443548691210419e-019, +12, 10.735452577471733, 6.944357314519752e-019, +12, 11.229217991232872, 4.4666546191302752e-019, +12, 11.229217998683453, 4.4666540313320006e-019, +12, 11.70328252017498, 2.9048073087968165e-019, +12, 11.703282527625561, 2.9048072811110897e-019, +12, 12.068153090775013, 1.1197702118472231e-019, +12, 12.068153098225594, 1.1197723483874788e-019, +13, 0.74004656821489334, 1.1833107184182451e-006, +13, 0.74004657566547394, 1.1833097788321784e-006, +13, 1.5553053691983223, 9.7255030271643972e-009, +13, 1.5553053766489029, 9.7254989421162363e-009, +13, 2.3478806391358376, 1.7766237223855854e-010, +13, 2.3478806465864182, 1.7766232949140296e-010, +13, 3.1199393272399902, 5.7956070959333847e-012, +13, 3.1199393346905708, 5.7956067491263655e-012, +13, 3.8728964179754257, 2.9884476000191141e-013, +13, 3.8728964254260063, 2.9884474795319482e-013, +13, 4.6076695621013641, 2.2511499024927438e-014, +13, 4.6076695695519447, 2.2511492228003123e-014, +13, 5.3248289301991463, 2.3433299337790734e-015, +13, 5.3248289376497269, 2.3433296697120652e-015, +13, 6.024680033326149, 3.2334220967999432e-016, +13, 6.0246800407767296, 3.2334220842696106e-016, +13, 6.7073097303509712, 5.7246438539858037e-017, +13, 6.7073097378015518, 5.7246428548181273e-017, +13, 7.3726105690002441, 1.2665024613881524e-017, +13, 7.3726105764508247, 1.2665026479377931e-017, +13, 8.0202914103865623, 3.4243381685006812e-018, +13, 8.0202914178371429, 3.4243378550191225e-018, +13, 8.6498793810606003, 1.1097375058286432e-018, +13, 8.6498793885111809, 1.1097372565619852e-018, +13, 9.2607174664735794, 4.2345371873704953e-019, +13, 9.26071747392416, 4.234535720073341e-019, +13, 9.8519651964306831, 1.8698553775808502e-019, +13, 9.8519652038812637, 1.8698556036241362e-019, +13, 10.4226189032197, 9.3834845010114218e-020, +13, 10.42261891067028, 9.3834849389696859e-020, +13, 10.971594020724297, 5.2445253216776838e-020, +13, 10.971594028174877, 5.244524330346984e-020, +13, 11.497980736196041, 3.1824489086388546e-020, +13, 11.497980743646622, 3.1824504032698097e-020, +13, 12.001743614673615, 2.0418153275918044e-020, +13, 12.001743622124195, 2.0418144824511038e-020, +13, 12.485165499150753, 1.322118298528861e-020, +13, 12.485165506601334, 1.3221186083014843e-020, +13, 12.954543322324753, 8.948147552026443e-021, +13, 12.954543329775333, 8.9481497369716256e-021, +13, 13.141756847500801, 6.2261736884111559e-021, +13, 13.141756854951382, 6.22616137965588e-021, +14, 0.74509535729885101, 8.6479103419423106e-007, +14, 0.74509536474943161, 8.6479038219181041e-007, +14, 1.5648643523454666, 6.1650149037400714e-009, +14, 1.5648643597960472, 6.1650125500027851e-009, +14, 2.3629250749945641, 9.7577785849465913e-011, +14, 2.3629250824451447, 9.7577755012051767e-011, +14, 3.1414090842008591, 2.7542691144474049e-012, +14, 3.1414090916514397, 2.754268644924632e-012, +14, 3.9017298147082329, 1.2272153763375018e-013, +14, 3.9017298221588135, 1.2272152123703597e-013, +14, 4.6448303312063217, 7.978322520490151e-015, +14, 4.6448303386569023, 7.9783225037342658e-015, +14, 5.3713301867246628, 7.1601479759177548e-016, +14, 5.3713301941752434, 7.1601474269921559e-016, +14, 6.0816079154610634, 8.5112993423908193e-017, +14, 6.081607922911644, 8.5112990415141843e-017, +14, 6.775848351418972, 1.2975876577628266e-017, +14, 6.7758483588695526, 1.2975877961248016e-017, +14, 7.454069696366787, 2.472008704163831e-018, +14, 7.4540697038173676, 2.4720086738065271e-018, +14, 8.1161380037665367, 5.7588911760227473e-019, +14, 8.1161380112171173, 5.7588919455128341e-019, +14, 8.7617733329534531, 1.6104402650810633e-019, +14, 8.7617733404040337, 1.6104400596562633e-019, +14, 9.3905506879091263, 5.3175849261375426e-020, +14, 9.3905506953597069, 5.3175840555484183e-020, +14, 10.001898743212223, 2.0418615673652841e-020, +14, 10.001898750662804, 2.0418619107744165e-020, +14, 10.595101684331894, 8.9828277730487657e-021, +14, 10.595101691782475, 8.9828244400191064e-021, +14, 11.169315472245216, 4.4582227129137701e-021, +14, 11.169315479695797, 4.4582210840169188e-021, +14, 11.723624959588051, 2.4539473008929182e-021, +14, 11.723624967038631, 2.4539478386423601e-021, +14, 12.25720601528883, 1.4682386166943286e-021, +14, 12.25720602273941, 1.4682385418038961e-021, +14, 12.76973832398653, 9.3346251997410079e-022, +14, 12.769738331437111, 9.3346223359077701e-022, +14, 13.262287445366383, 6.0874087090840453e-022, +14, 13.262287452816963, 6.0874060113413987e-022, +14, 13.73819725215435, 4.0622784880680064e-022, +14, 13.738197259604931, 4.0622806176204874e-022, +15, 0.74963488429784775, 6.4472609076683897e-007, +15, 0.74963489174842834, 6.4472546314886359e-007, +15, 1.5734371542930603, 4.0226647054678587e-009, +15, 1.5734371617436409, 4.0226622606167611e-009, +15, 2.3763899058103561, 5.5678382926067953e-011, +15, 2.3763899132609367, 5.5678366001298979e-011, +15, 3.1605874672532082, 1.3728924222156093e-012, +15, 3.1605874747037888, 1.3728922232543816e-012, +15, 3.9274342954158783, 5.3378856950128611e-014, +15, 3.9274343028664589, 5.3378843159211659e-014, +15, 4.6778862848877907, 3.0250264329161316e-015, +15, 4.6778862923383713, 3.0250255465237931e-015, +15, 5.4125945195555687, 2.3643655178483816e-016, +15, 5.4125945270061493, 2.364365094900239e-016, +15, 6.1319867372512817, 2.4459487536429736e-017, +15, 6.1319867447018623, 2.4459487650611821e-017, +15, 6.8363150134682655, 3.2436206211824709e-018, +15, 6.8363150209188461, 3.2436197176022979e-018, +15, 7.5256842151284218, 5.3739371041542508e-019, +15, 7.5256842225790024, 5.3739376909794387e-019, +15, 8.2000685408711433, 1.088934674475772e-019, +15, 8.2000685483217239, 1.0889347191934601e-019, +15, 8.8593204915523529, 2.6504714435038781e-020, +15, 8.8593204990029335, 2.6504716387206021e-020, +15, 9.5031745359301567, 7.6282884779808578e-021, +15, 9.5031745433807373, 7.6282871890206407e-021, +15, 10.131247609853745, 2.5596033506939261e-021, +15, 10.131247617304325, 2.5596033059431966e-021, +15, 10.743038579821587, 9.8815320291260219e-022, +15, 10.743038587272167, 9.881528789722149e-022, +15, 11.337930642068386, 4.3327572929097578e-022, +15, 11.337930649518967, 4.3327579478065768e-022, +15, 11.91520432382822, 2.1290839700926256e-022, +15, 11.915204331278801, 2.1290844593454176e-022, +15, 12.47407853603363, 1.1555853827459651e-022, +15, 12.474078543484211, 1.1555851200022939e-022, +15, 13.013818167150021, 6.8144327801967497e-023, +15, 13.013818174600601, 6.814431722582805e-023, +15, 13.533991023898125, 4.2798966509192708e-023, +15, 13.533991031348705, 4.279897117134478e-023, +15, 14.035010702908039, 2.7914921195937233e-023, +15, 14.03501071035862, 2.7914916878659476e-023, +15, 14.518910378217697, 1.833772281462441e-023, +15, 14.518910385668278, 1.8337712497676989e-023, +15, 14.989013738930225, 1.2608384937256306e-023, +15, 14.989013746380806, 1.2608378195451462e-023, +16, 0.75374705344438553, 4.8915337496543224e-007, +16, 0.75374706089496613, 4.8915306793373716e-007, +16, 1.5811846181750298, 2.6923132475156358e-009, +16, 1.5811846256256104, 2.692312137537266e-009, +16, 2.3885360583662987, 3.2852614483624288e-011, +16, 2.3885360658168793, 3.2852599884042077e-011, +16, 3.1778582483530045, 7.1354837117579206e-013, +16, 3.1778582558035851, 7.1354819499657137e-013, +16, 3.9505422189831734, 2.4415794649042575e-014, +16, 3.950542226433754, 2.4415790464100997e-014, +16, 4.7075485289096832, 1.2166614671909252e-015, +16, 4.7075485363602638, 1.2166612061656969e-015, +16, 5.4495479688048363, 8.3551487091643194e-017, +16, 5.4495479762554169, 8.3551474485434551e-017, +16, 6.1770017296075821, 7.5892566535084655e-018, +16, 6.1770017370581627, 7.5892568568026215e-018, +16, 6.890208899974823, 8.8323530753260686e-019, +16, 6.8902089074254036, 8.8323505679897636e-019, +16, 7.5893355086445808, 1.2838109403040181e-019, +16, 7.5893355160951614, 1.2838108671707829e-019, +16, 8.2744322568178177, 2.2821684437156804e-020, +16, 8.2744322642683983, 2.282168749495082e-020, +16, 8.9454451054334641, 4.8744259157716707e-021, +16, 8.9454451128840446, 4.8744247029595045e-021, +16, 9.6022209450602531, 1.2319495868217162e-021, +16, 9.6022209525108337, 1.2319494772820823e-021, +16, 10.244509845972061, 3.6348978875812834e-022, +16, 10.244509853422642, 3.6348985260615e-022, +16, 10.871965378522873, 1.2367742746291744e-022, +16, 10.871965385973454, 1.2367739126564003e-022, +16, 11.484144628047943, 4.7970119302772392e-023, +16, 11.484144635498524, 4.7970127598781626e-023, +16, 12.080510623753071, 2.0970543482083159e-023, +16, 12.080510631203651, 2.0970540591110336e-023, +16, 12.660443000495434, 1.0212748080573996e-023, +16, 12.660443007946014, 1.0212749016622482e-023, +16, 13.223268158733845, 5.4721418402402487e-024, +16, 13.223268166184425, 5.4721424729500052e-024, +16, 13.768333427608013, 3.1810966077030606e-024, +16, 13.768333435058594, 3.181096582631882e-024, +16, 14.295174412429333, 1.9706877841945116e-024, +16, 14.295174419879913, 1.9706884118909232e-024, +16, 14.803859077394009, 1.2794879837821395e-024, +16, 14.803859084844589, 1.2794882377473996e-024, +16, 15.295545108616352, 8.4344716828413924e-025, +16, 15.295545116066933, 8.4344683346343458e-025, +16, 15.772794611752033, 5.7392825698566701e-025, +16, 15.772794619202614, 5.7392822347696177e-025, +16, 16.216887570917606, 3.6997343524479107e-025, +16, 16.216887578368187, 3.6997346587299121e-025, +17, 0.75749634951353073, 3.7692745372019008e-007, +17, 0.75749635696411133, 3.7692700070692814e-007, +17, 1.5882330387830734, 1.8429395479824224e-009, +17, 1.588233046233654, 1.8429387676315583e-009, +17, 2.3995678052306175, 1.9967644390215291e-011, +17, 2.3995678126811981, 1.9967637238366132e-011, +17, 3.1935207024216652, 3.8482056723979746e-013, +17, 3.1935207098722458, 3.8482046172543379e-013, +17, 3.9714667573571205, 1.1675233373393322e-014, +17, 3.9714667648077011, 1.167523092849099e-014, +17, 4.7343658432364464, 5.1547822958137584e-016, +17, 4.734365850687027, 5.1547809052809859e-016, +17, 5.4829004630446434, 3.1343625323079668e-017, +17, 5.482900470495224, 3.1343618068151562e-017, +17, 6.2175545245409012, 2.5193828294777807e-018, +17, 6.2175545319914818, 2.5193819999045696e-018, +17, 6.9386604055762291, 2.5933718219907985e-019, +17, 6.9386604130268097, 2.5933719595613529e-019, +17, 7.6464280635118484, 3.3330158772752984e-020, +17, 7.646428070962429, 3.3330160862180195e-020, +17, 8.3409634903073311, 5.2379397998875143e-021, +17, 8.3409634977579117, 5.2379386588488221e-021, +17, 9.0222802385687828, 9.8908851451647746e-022, +17, 9.0222802460193634, 9.8908823476058462e-022, +17, 9.6903063133358955, 2.2108045577850313e-022, +17, 9.6903063207864761, 2.2108041448570457e-022, +17, 10.344887860119343, 5.7731399489054422e-023, +17, 10.344887867569923, 5.773138110616153e-023, +17, 10.98579066246748, 1.7407181648032493e-023, +17, 10.98579066991806, 1.7407180865759728e-023, +17, 11.6127003505826, 5.9955236166794974e-024, +17, 11.61270035803318, 5.9955216352412096e-024, +17, 12.225222736597061, 2.3349804655788398e-024, +17, 12.225222744047642, 2.3349807732238287e-024, +17, 12.82288621366024, 1.0179952851287067e-024, +17, 12.822886221110821, 1.0179953150198629e-024, +17, 13.405150465667248, 4.9176017252558557e-025, +17, 13.405150473117828, 4.9176033251919074e-025, +17, 13.971429191529751, 2.6038182860572718e-025, +17, 13.971429198980331, 2.603818076773733e-025, +17, 14.521142840385437, 1.4930454888989484e-025, +17, 14.521142847836018, 1.4930452390494677e-025, +17, 15.053831778466702, 9.123082958623521e-026, +17, 15.053831785917282, 9.1230791767726492e-026, +17, 15.569381833076477, 5.8751079623571136e-026, +17, 15.569381840527058, 5.8751075038868982e-026, +17, 16.068407364189625, 3.8749149875575966e-026, +17, 16.068407371640205, 3.8749167349006019e-026, +17, 16.552637793123722, 2.5963438998656586e-026, +17, 16.552637800574303, 2.5963440101195602e-026, +17, 17.024716928601265, 1.7949322494851864e-026, +17, 17.024716936051846, 1.7949319523018589e-026, +17, 17.346179291605949, 2.8309800520891487e-027, +17, 17.34617929905653, 2.8309773118757838e-027, +18, 0.76093439012765884, 2.9450240370798458e-007, +18, 0.76093439757823944, 2.9450203771031953e-007, +18, 1.5946831777691841, 1.2871185298229725e-009, +18, 1.5946831852197647, 1.2871177488403049e-009, +18, 2.4096476435661316, 1.2461251822064865e-011, +18, 2.4096476510167122, 1.2461248257070009e-011, +18, 3.207812137901783, 2.1447968570473172e-013, +18, 3.2078121453523636, 2.1447959182366632e-013, +18, 3.9905342757701874, 5.8079896477904645e-015, +18, 3.990534283220768, 5.8079874820498712e-015, +18, 4.7587697133421898, 2.2873919040338732e-016, +18, 4.7587697207927704, 2.2873918091132165e-016, +18, 5.5132071524858475, 1.2399411155563791e-017, +18, 5.5132071599364281, 1.2399410449684862e-017, +18, 6.2543457671999931, 8.8806343367361896e-019, +18, 6.2543457746505737, 8.8806339445463331e-019, +18, 6.9825416058301926, 8.1418645242373546e-020, +18, 6.9825416132807732, 8.1418638978404545e-020, +18, 7.6980366632342339, 9.3166546160183016e-021, +18, 7.6980366706848145, 9.316653065404742e-021, +18, 8.4009775668382645, 1.3033282065831878e-021, +18, 8.4009775742888451, 1.303327910841165e-021, +18, 9.0914276838302612, 2.1906432409842348e-022, +18, 9.0914276912808418, 2.1906432254533542e-022, +18, 9.7693748101592064, 4.3589910796802725e-023, +18, 9.769374817609787, 4.3589901608432619e-023, +18, 10.434735849499702, 1.0137066700093108e-023, +18, 10.434735856950283, 1.0137066734442173e-023, +18, 11.087359227240086, 2.7240107890987674e-024, +18, 11.087359234690666, 2.7240105244068185e-024, +18, 11.727025918662548, 8.371655684372496e-025, +18, 11.727025926113129, 8.3716527086860413e-025, +18, 12.353449679911137, 2.9146730821631173e-025, +18, 12.353449687361717, 2.9146728028573778e-025, +18, 12.966277495026588, 1.1392339405640447e-025, +18, 12.966277502477169, 1.1392339608927589e-025, +18, 13.565091922879219, 4.9545881072919797e-026, +18, 13.5650919303298, 4.9545866952502942e-026, +18, 14.149418227374554, 2.3758167105055241e-026, +18, 14.149418234825134, 2.3758158313872783e-026, +18, 14.718741856515408, 1.2442765527084641e-026, +18, 14.718741863965988, 1.244276230271342e-026, +18, 15.272546909749508, 7.0424811711899878e-027, +18, 15.272546917200089, 7.0424832994636221e-027, +18, 15.810395196080208, 4.2497327978932225e-027, +18, 15.810395203530788, 4.2497340544704781e-027, +18, 16.332078844308853, 2.7060819868792312e-027, +18, 16.332078851759434, 2.7060823827611486e-027, +18, 16.83788288384676, 1.778958105553305e-027, +18, 16.83788289129734, 1.7789585636337179e-027, +18, 17.328916251659393, 1.1828714637450282e-027, +18, 17.328916259109974, 1.182871994927067e-027, +18, 17.807191208004951, 8.1726141746863567e-028, +18, 17.807191215455532, 8.1726174566351736e-028, +18, 18.284037873148918, 5.6912247207101229e-028, +18, 18.284037880599499, 5.691222218060101e-028, +18, 18.392694972455502, 5.2831137523744097e-028, +18, 18.392694979906082, 5.2831145046877764e-028, +19, 0.764103002846241, 2.3298449147644669e-007, +19, 0.76410301029682159, 2.3298424269489823e-007, +19, 1.6006165370345116, 9.1529116957755399e-010, +19, 1.6006165444850922, 9.1529068365546486e-010, +19, 2.4189066812396049, 7.9633891310433137e-012, +19, 2.4189066886901855, 7.9633842469171524e-012, +19, 3.220923513174057, 1.2312031507978179e-013, +19, 3.2209235206246376, 1.2312028082814339e-013, +19, 4.0080065280199051, 2.9933906948263948e-015, +19, 4.0080065354704857, 2.9933899839494794e-015, +19, 4.7811048328876495, 1.0579214187674311e-016, +19, 4.7811048403382301, 1.0579211525173792e-016, +19, 5.5409095361828804, 5.1437209226821869e-018, +19, 5.540909543633461, 5.1437201098803477e-018, +19, 6.2879297584295273, 3.30285370901757e-019, +19, 6.2879297658801079, 3.3028526990782213e-019, +19, 7.022538423538208, 2.7137393350465049e-020, +19, 7.0225384309887886, 2.7137390145037245e-020, +19, 7.7450010478496552, 2.7820488626315749e-021, +19, 7.7450010553002357, 2.7820487012081861e-021, +19, 8.4554945304989815, 3.4859333557441231e-022, +19, 8.4554945379495621, 3.4859329845518359e-022, +19, 9.1541195586323738, 5.2474008771752571e-023, +19, 9.1541195660829544, 5.2474000384032056e-023, +19, 9.8409088104963303, 9.3512638696111626e-024, +19, 9.8409088179469109, 9.3512648493398201e-024, +19, 10.515832215547562, 1.9479937239944536e-024, +19, 10.515832222998142, 1.9479938575974556e-024, +19, 11.178800173103809, 4.69085412141189e-025, +19, 11.17880018055439, 4.6908548720156987e-025, +19, 11.829665213823318, 1.2928024618486752e-025, +19, 11.829665221273899, 1.2928026753018633e-025, +19, 12.468222707509995, 4.0409290148689646e-026, +19, 12.468222714960575, 4.04092946286875e-026, +19, 13.094211108982563, 1.4204369152574e-026, +19, 13.094211116433144, 1.4204368039399753e-026, +19, 13.707312539219856, 5.5697729454842655e-027, +19, 13.707312546670437, 5.5697729267586886e-027, +19, 14.307154916226864, 2.4168995964876991e-027, +19, 14.307154923677444, 2.4168993118015141e-027, +19, 14.893317893147469, 1.151182873307859e-027, +19, 14.893317900598049, 1.151183249370605e-027, +19, 15.465346492826939, 5.9684896488404262e-028, +19, 15.465346500277519, 5.9684880973262032e-028, +19, 16.022779874503613, 3.3368863785415361e-028, +19, 16.022779881954193, 3.3368858888570371e-028, +19, 16.565208047628403, 1.988896282534073e-028, +19, 16.565208055078983, 1.9888966397094828e-028, +19, 17.092378154397011, 1.2511355195873936e-028, +19, 17.092378161847591, 1.2511357084655119e-028, +19, 17.604376800358295, 8.1764674788794317e-029, +19, 17.604376807808876, 8.1764689419338323e-029, +19, 18.101884864270687, 5.4403818799662857e-029, +19, 18.101884871721268, 5.4403811124044756e-029, +19, 18.586358889937401, 3.703368785213425e-029, +19, 18.586358897387981, 3.7033672461047739e-029, +19, 19.059829846024513, 2.5704197367132541e-029, +19, 19.059829853475094, 2.5704186883245258e-029, +20, 0.76703650504350662, 1.8640212188134082e-007, +20, 0.76703651249408722, 1.8640189110524636e-007, +20, 1.6060998290777206, 6.6157054588464647e-010, +20, 1.6060998365283012, 6.6157015121944875e-010, +20, 2.4274520501494408, 5.1991605763036711e-012, +20, 2.4274520576000214, 5.1991575903475782e-012, +20, 3.2330104410648346, 7.2582820146985349e-014, +20, 3.2330104485154152, 7.2582783832962019e-014, +20, 4.0240962356328964, 1.5927986670250318e-015, +20, 4.024096243083477, 1.5927979999140583e-015, +20, 4.8016504645347595, 5.0788048744312721e-017, +20, 4.8016504719853401, 5.0788029685345059e-017, +20, 5.5663639381527901, 2.2269814628583385e-018, +20, 5.5663639456033707, 2.2269809381302064e-018, +20, 6.3187519386410713, 1.2891132499721331e-019, +20, 6.3187519460916519, 1.2891130172541847e-019, +20, 7.0591993033885956, 9.5451218618123886e-021, +20, 7.0591993108391762, 9.5451218640099815e-021, +20, 7.7879889234900475, 8.8158015376044649e-022, +20, 7.7879889309406281, 8.8158004848661898e-022, +20, 8.5053204819560051, 9.9494735027566205e-023, +20, 8.5053204894065857, 9.9494722416437504e-023, +20, 9.2113229855895042, 1.3487881180413846e-023, +20, 9.2113229930400848, 1.3487880891331086e-023, +20, 9.9060632660984993, 2.1645350197982161e-024, +20, 9.9060632735490799, 2.1645348970951956e-024, +20, 10.589551687240601, 4.0607366596729865e-025, +20, 10.589551694691181, 4.0607361603086007e-025, +20, 11.26174583286047, 8.808202739315011e-026, +20, 11.26174584031105, 8.8082017838145519e-026, +20, 11.922552742063999, 2.1876047727436381e-026, +20, 11.92255274951458, 2.1876050426774313e-026, +20, 12.571830086410046, 6.1662495078304429e-027, +20, 12.571830093860626, 6.1662499348774014e-027, +20, 13.209386698901653, 1.9567173794914837e-027, +20, 13.209386706352234, 1.9567170332738984e-027, +20, 13.834982834756374, 6.9373607598036741e-028, +20, 13.834982842206955, 6.9373595897190232e-028, +20, 14.448330782353878, 2.7280690089401278e-028, +20, 14.448330789804459, 2.7280680945996177e-028, +20, 15.049096845090389, 1.1813689543546431e-028, +20, 15.04909685254097, 1.181369139348639e-028, +20, 15.636906251311302, 5.5924252241628636e-029, +20, 15.636906258761883, 5.5924267990651051e-029, +20, 16.211354024708271, 2.8725730797162321e-029, +20, 16.211354032158852, 2.8725722552333354e-029, +20, 16.772026851773262, 1.5875830143022102e-029, +20, 16.772026859223843, 1.5875829520216891e-029, +20, 17.318544775247574, 9.3495852893429768e-030, +20, 17.318544782698154, 9.3495854282408101e-030, +20, 17.850637152791023, 5.8080378869545303e-030, +20, 17.850637160241604, 5.8080398155538604e-030, +20, 18.36827152967453, 3.766778846313291e-030, +20, 18.368271537125111, 3.766779811191838e-030, +20, 18.871843047440052, 2.5002689211421573e-030, +20, 18.871843054890633, 2.5002682344308047e-030, +20, 19.362363085150719, 1.674243648785181e-030, +20, 19.362363092601299, 1.6742442653555633e-030, +20, 19.841450870037079, 1.1710157057806629e-030, +20, 19.841450877487659, 1.1710152732309025e-030, +20, 20.30974967777729, 8.0586953650643033e-031, +20, 20.309749685227871, 8.0586997818188476e-031, +21, 0.76976337283849716, 1.5066428073454916e-007, +21, 0.76976338028907776, 1.5066414246643623e-007, +21, 1.6111882776021957, 4.8530823596591033e-010, +21, 1.6111882850527763, 4.8530796828419519e-010, +21, 2.4353722333908081, 3.4610451821120009e-012, +21, 2.4353722408413887, 3.4610441424017983e-012, +21, 3.2442012280225754, 4.3835042623395894e-014, +21, 3.244201235473156, 4.3835023934688873e-014, +21, 4.0389783605933189, 8.7240487039547189e-016, +21, 4.0389783680438995, 8.7240461492198342e-016, +21, 4.820635624229908, 2.5219465898201733e-017, +21, 4.8206356316804886, 2.5219460854936753e-017, +21, 5.5898616313934326, 1.0022039268504888e-018, +21, 5.5898616388440132, 1.0022036172718784e-018, +21, 6.3471750691533089, 5.2559389652856588e-020, +21, 6.3471750766038895, 5.2559375594443955e-020, +21, 7.0929690599441528, 3.5247425965088507e-021, +21, 7.0929690673947334, 3.5247425089738368e-021, +21, 7.827539324760437, 2.9476660458905233e-022, +21, 7.8275393322110176, 2.9476655571904849e-022, +21, 8.551102802157402, 3.0115631228572582e-023, +21, 8.5511028096079826, 3.011562652643058e-023, +21, 9.2638102099299431, 3.6952283110718485e-024, +21, 9.2638102173805237, 3.6952283319575928e-024, +21, 9.9657547101378441, 5.3669656457006436e-025, +21, 9.9657547175884247, 5.3669649762144234e-025, +21, 10.656977899372578, 9.1124256917763825e-026, +21, 10.656977906823158, 9.1124268540483906e-026, +21, 11.337473809719086, 1.7890692227696762e-026, +21, 11.337473817169666, 1.7890693666894125e-026, +21, 12.007191583514214, 4.0227743879756425e-027, +21, 12.007191590964794, 4.0227743211391833e-027, +21, 12.666037052869797, 1.0270242765644747e-027, +21, 12.666037060320377, 1.0270242120978496e-027, +21, 13.313873596489429, 2.9538104523737974e-028, +21, 13.31387360394001, 2.9538105861327128e-028, +21, 13.950522527098656, 9.5012147708737886e-029, +21, 13.950522534549236, 9.5012121359051193e-029, +21, 14.575763396918774, 3.3946835963332503e-029, +21, 14.575763404369354, 3.3946830842745097e-029, +21, 15.189334601163864, 1.338384258083857e-029, +21, 15.189334608614445, 1.3383838228935191e-029, +21, 15.790935188531876, 5.7848622633191873e-030, +21, 15.790935195982456, 5.7848637716726903e-030, +21, 16.380228973925114, 2.7230499400143476e-030, +21, 16.380228981375694, 2.7230500761171659e-030, +21, 16.956853300333023, 1.3866916070525852e-030, +21, 16.956853307783604, 1.3866911116291402e-030, +21, 17.520435951650143, 7.5812793671458848e-031, +21, 17.520435959100723, 7.5812815048755598e-031, +21, 18.070626437664032, 4.4134618820380508e-031, +21, 18.070626445114613, 4.4134600003014153e-031, +21, 18.607151560485363, 2.7073121862111579e-031, +21, 18.607151567935944, 2.7073119631598685e-031, +21, 19.129908226430416, 1.7405231919358924e-031, +21, 19.129908233880997, 1.7405224578827498e-031, +21, 19.639103204011917, 1.149909852362787e-031, +21, 19.639103211462498, 1.1499093604025187e-031, +21, 20.135416276752949, 7.7057380617546439e-032, +21, 20.135416284203529, 7.7057377584979628e-032, +21, 20.62007824331522, 5.313635434227207e-032, +21, 20.6200782507658, 5.313638182607342e-032, +21, 21.09471806883812, 3.6998772136443968e-032, +21, 21.0947180762887, 3.6998750382256628e-032, +21, 21.513655178248882, 2.1423087294246753e-032, +21, 21.513655185699463, 2.1423066695903474e-032, +22, 0.77230742573738098, 1.229185164418409e-007, +22, 0.77230743318796158, 1.2291832454378835e-007, +22, 1.6159280240535736, 3.6084429032500014e-010, +22, 1.6159280315041542, 3.6084396590066408e-010, +22, 2.4427410438656807, 2.3451786403587014e-012, +22, 2.4427410513162613, 2.3451775949384816e-012, +22, 3.2546027079224586, 2.7062134880156874e-014, +22, 3.2546027153730392, 2.7062125966134374e-014, +22, 4.0527982860803604, 4.9058357404375516e-016, +22, 4.052798293530941, 4.9058348176902023e-016, +22, 4.8382501602172852, 1.2913921603181287e-017, +22, 4.8382501676678658, 1.2913917228554348e-017, +22, 5.6116434335708618, 4.6717185843067393e-019, +22, 5.6116434410214424, 4.6717179776425538e-019, +22, 6.3734981417655945, 2.2296903198511069e-020, +22, 6.3734981492161751, 2.2296900974904039e-020, +22, 7.1242129951715469, 1.3604387314615133e-021, +22, 7.1242130026221275, 1.3604385613902272e-021, +22, 7.8640931621193886, 1.0348631251961015e-022, +22, 7.8640931695699692, 1.03486285303848e-022, +22, 8.5933686941862106, 9.6152630844306075e-024, +22, 8.5933687016367912, 9.6152607923175558e-024, +22, 9.3122070804238319, 1.0727676244494742e-024, +22, 9.3122070878744125, 1.0727675822781486e-024, +22, 10.020721986889839, 1.4165824772693852e-025, +22, 10.02072199434042, 1.416582491355437e-025, +22, 10.718979395925999, 2.1866391305081649e-026, +22, 10.718979403376579, 2.1866388838497643e-026, +22, 11.407001882791519, 3.9031522459423558e-027, +22, 11.4070018902421, 3.9031521089045438e-027, +22, 12.084771521389484, 7.9802702761510913e-028, +22, 12.084771528840065, 7.980269670975788e-028, +22, 12.752231821417809, 1.8530613678900598e-028, +22, 12.752231828868389, 1.8530616824287783e-028, +22, 13.409288860857487, 4.8494798585916549e-029, +22, 13.409288868308067, 4.8494785536449382e-029, +22, 14.05581197142601, 1.4202884091535673e-029, +22, 14.055811978876591, 1.4202885442138583e-029, +22, 14.691633984446526, 4.6247809754088509e-030, +22, 14.691633991897106, 4.6247795457938258e-030, +22, 15.316551595926285, 1.6639745508668973e-030, +22, 15.316551603376865, 1.6639743599938902e-030, +22, 15.93032594025135, 6.5756901693418488e-031, +22, 15.930325947701931, 6.575690654043178e-031, +22, 16.532684214413166, 2.8372660249774888e-031, +22, 16.532684221863747, 2.8372664253810075e-031, +22, 17.123323194682598, 1.3286347918438753e-031, +22, 17.123323202133179, 1.328634334065038e-031, +22, 17.701916337013245, 6.7120509402607989e-032, +22, 17.701916344463825, 6.7120512896479518e-032, +22, 18.268127046525478, 3.6325184300463703e-032, +22, 18.268127053976059, 3.6325181235491734e-032, +22, 18.821632660925388, 2.0914308743910646e-032, +22, 18.821632668375969, 2.0914299057002497e-032, +22, 19.362165823578835, 1.2686800121696762e-032, +22, 19.362165831029415, 1.2686799446403407e-032, +22, 19.88958266377449, 8.0696445865656865e-033, +22, 19.889582671225071, 8.0696450863153928e-033, +22, 20.403966307640076, 5.2979414488418604e-033, +22, 20.403966315090656, 5.2979393097828398e-033, +22, 20.905758522450924, 3.5438052686101887e-033, +22, 20.905758529901505, 3.5438058521502753e-033, +22, 21.39586365967989, 2.4059587559014193e-033, +22, 21.39586366713047, 2.4059592126750793e-033, +22, 21.87561222910881, 1.686377885007472e-033, +22, 21.875612236559391, 1.6863776494421034e-033, +22, 22.346770018339157, 1.1684307972912237e-033, +22, 22.346770025789738, 1.1684310754271521e-033, +22, 22.618329457938671, 3.0366386951575348e-034, +22, 22.618329465389252, 3.0366315962617322e-034, +23, 0.77468881756067276, 1.0114160950347676e-007, +23, 0.77468882501125336, 1.0114149032370741e-007, +23, 1.6203579902648926, 2.7163743073571882e-010, +23, 1.6203579977154732, 2.7163720774540249e-010, +23, 2.4496206343173981, 1.6150650901954226e-012, +23, 2.4496206417679787, 1.6150639831714421e-012, +23, 3.2643046677112579, 1.7046911971326696e-014, +23, 3.2643046751618385, 1.7046904575466703e-014, +23, 4.0656779706478119, 2.8259863440888197e-016, +23, 4.0656779780983925, 2.8259849772579011e-016, +23, 4.8546530231833458, 6.8011510032153151e-018, +23, 4.8546530306339264, 6.8011494716482078e-018, +23, 5.6319104433059692, 2.2488464281640756e-019, +23, 5.6319104507565498, 2.2488459534517975e-019, +23, 6.3979701548814774, 9.8079791952490223e-021, +23, 6.397970162332058, 9.8079765385497614e-021, +23, 7.1532344222068787, 5.4671937485617472e-022, +23, 7.1532344296574593, 5.4671917378843881e-022, +23, 7.8980152830481529, 3.7986233108918277e-023, +23, 7.8980152904987335, 3.7986220021765903e-023, +23, 8.6325527653098106, 3.2231569433958688e-024, +23, 8.6325527727603912, 3.2231565617086114e-024, +23, 9.3570273742079735, 3.2834969778924849e-025, +23, 9.3570273816585541, 3.2834965760335941e-025, +23, 10.071568876504898, 3.9585335209485738e-026, +23, 10.071568883955479, 3.958533284993818e-026, +23, 10.776262499392033, 5.5783111048939248e-027, +23, 10.776262506842613, 5.5783106522452834e-027, +23, 11.471153371036053, 9.0901545746996052e-028, +23, 11.471153378486633, 9.0901530603778864e-028, +23, 12.156249642372131, 1.6968039360579984e-028, +23, 12.156249649822712, 1.6968035736701341e-028, +23, 12.831524632871151, 3.5977409707902412e-029, +23, 12.831524640321732, 3.5977400460720119e-029, +23, 13.496918246150017, 8.5996241514863787e-030, +23, 13.496918253600597, 8.5996216693376864e-030, +23, 14.152337834239006, 2.301386888748009e-030, +23, 14.152337841689587, 2.3013866363420915e-030, +23, 14.797658666968346, 6.8517867573579195e-031, +23, 14.797658674418926, 6.8517865061112645e-031, +23, 15.432724215090275, 2.2560267724720382e-031, +23, 15.432724222540855, 2.2560264136538832e-031, +23, 16.057346440851688, 8.1688281380273512e-032, +23, 16.057346448302269, 8.1688278348171516e-032, +23, 16.671306401491165, 3.2350057586674508e-032, +23, 16.671306408941746, 3.2350061703509374e-032, +23, 17.274355687201023, 1.3935974246555884e-032, +23, 17.274355694651604, 1.3935975649494885e-032, +23, 17.86621943116188, 6.494692001260146e-033, +23, 17.866219438612461, 6.4946923994178033e-033, +23, 18.446602113544941, 3.2567180669074382e-033, +23, 18.446602120995522, 3.2567169178931394e-033, +23, 19.015198193490505, 1.7458070339763389e-033, +23, 19.015198200941086, 1.7458065238164995e-033, +23, 19.571710675954819, 9.946196118534568e-034, +23, 19.571710683405399, 9.9461948954570997e-034, +23, 20.11588254570961, 5.9690525712299976e-034, +23, 20.115882553160191, 5.9690500193873946e-034, +23, 20.647547744214535, 3.7545858767414626e-034, +23, 20.647547751665115, 3.7545848159991635e-034, +23, 21.166708528995514, 2.4468390226112094e-034, +23, 21.166708536446095, 2.4468378891837283e-034, +23, 21.673638753592968, 1.6305350714270763e-034, +23, 21.673638761043549, 1.6305353199615473e-034, +23, 22.168985672295094, 1.0990783133763909e-034, +23, 22.168985679745674, 1.0990780643508099e-034, +23, 22.653797566890717, 7.660709966183589e-035, +23, 22.653797574341297, 7.6607108605632843e-035, +23, 23.129408702254295, 5.3481086344930933e-035, +23, 23.129408709704876, 5.3481086507387228e-035, +24, 0.77692466974258423, 8.3878559509491768e-008, +24, 0.77692467719316483, 8.3878444500950374e-008, +24, 1.6245112344622612, 2.0682132657809845e-010, +24, 1.6245112419128418, 2.068211277333234e-010, +24, 2.4560637548565865, 1.1289636914686017e-012, +24, 2.4560637623071671, 1.1289631400035527e-012, +24, 3.2733832001686096, 1.0938619422732816e-014, +24, 3.2733832076191902, 1.0938612911479053e-014, +24, 4.077720619738102, 1.6643113288659459e-016, +24, 4.0777206271886826, 1.6643108721731801e-016, +24, 4.8699784204363823, 3.6754217074679444e-018, +24, 4.8699784278869629, 3.6754201672840378e-018, +24, 5.6508321389555931, 1.1149437498689269e-019, +24, 5.6508321464061737, 1.1149432883776919e-019, +24, 6.4208004623651505, 4.4601526574819404e-021, +24, 6.420800469815731, 4.4601509330870358e-021, +24, 7.1802876740694046, 2.279941873373783e-022, +24, 7.1802876815199852, 2.2799412884161901e-022, +24, 7.9296107068657875, 1.4524227687620892e-023, +24, 7.9296107143163681, 1.4524227325357687e-023, +24, 8.6690171509981155, 1.1297516597255878e-024, +24, 8.6690171584486961, 1.1297516022917642e-024, +24, 9.398697666823864, 1.05489876857462e-025, +24, 9.3986976742744446, 1.0548984739860872e-025, +24, 10.118794731795788, 1.1655531704609301e-026, +24, 10.118794739246368, 1.1655532065990126e-026, +24, 10.82940886169672, 1.5051895754488702e-027, +24, 10.829408869147301, 1.5051892821133279e-027, +24, 11.53060320019722, 2.2476895295962268e-028, +24, 11.5306032076478, 2.2476889060302806e-028, +24, 12.22240673750639, 3.844876383499449e-029, +24, 12.22240674495697, 3.8448759550255258e-029, +24, 12.904816634953022, 7.4714391018572407e-030, +24, 12.904816642403603, 7.4714395302486889e-030, +24, 13.577799834311008, 1.6370125904554994e-030, +24, 13.577799841761589, 1.6370124695278897e-030, +24, 14.241294123232365, 4.0168128083279772e-031, +24, 14.241294130682945, 4.016811469349949e-031, +24, 14.895208783447742, 1.0969746370532075e-031, +24, 14.895208790898323, 1.0969744744608578e-031, +24, 15.539424940943718, 3.315109989109058e-032, +24, 15.539424948394299, 3.3151090923815311e-032, +24, 16.173795841634274, 1.1026485108254938e-032, +24, 16.173795849084854, 1.1026484499551487e-032, +24, 16.798147104680538, 4.0158085477948419e-033, +24, 16.798147112131119, 4.0158088226660865e-033, +24, 17.412277333438396, 1.5934132234896702e-033, +24, 17.412277340888977, 1.5934135053593853e-033, +24, 18.015959389507771, 6.8540171917222488e-034, +24, 18.015959396958351, 6.8540185876176649e-034, +24, 18.608942970633507, 3.1800628171362954e-034, +24, 18.608942978084087, 3.1800629680378069e-034, +24, 19.190959438681602, 1.5836246914151322e-034, +24, 19.190959446132183, 1.5836252472988316e-034, +24, 19.76173035800457, 8.4137600917291117e-035, +24, 19.761730365455151, 8.4137587940032584e-035, +24, 20.320982187986374, 4.745679482731015e-035, +24, 20.320982195436954, 4.7456809155199022e-035, +24, 20.868470467627048, 2.8185196647984626e-035, +24, 20.868470475077629, 2.8185199366681781e-035, +24, 21.404018573462963, 1.7531167534135375e-035, +24, 21.404018580913544, 1.7531173016947469e-035, +24, 21.927576221525669, 1.1332672002404092e-035, +24, 21.92757622897625, 1.1332675797508253e-035, +24, 22.439299717545509, 7.5125238131908317e-036, +24, 22.43929972499609, 7.5125236509015167e-036, +24, 22.939641229808331, 5.0568780187314363e-036, +24, 22.939641237258911, 5.0568784513528091e-036, +24, 23.429403953254223, 3.4736003627413405e-036, +24, 23.429403960704803, 3.4735987495009831e-036, +24, 23.90970042347908, 2.4387081321665308e-036, +24, 23.909700430929661, 2.4387083910949941e-036, +24, 24.38177253305912, 1.694733860647387e-036, +24, 24.381772540509701, 1.694733324885658e-036, +25, 0.77902968227863312, 7.0067469371321597e-008, +25, 0.77902968972921371, 7.0067352105092841e-008, +25, 1.6284160688519478, 1.5913112796142118e-010, +25, 1.6284160763025284, 1.5913095865429296e-010, +25, 2.4621154814958572, 8.0010005048491295e-013, +25, 2.4621154889464378, 8.0009951288958997e-013, +25, 3.2819032743573189, 7.1398107739385184e-015, +25, 3.2819032818078995, 7.1398064213538464e-015, +25, 4.0890141874551773, 1.0003569839311091e-016, +25, 4.0890141949057579, 1.0003565214949822e-016, +25, 4.8843406066298485, 2.0339987591563894e-018, +25, 4.8843406140804291, 2.0339981157202125e-018, +25, 5.6685525178909302, 5.6799254581074817e-020, +25, 5.6685525253415108, 5.6799245689717146e-020, +25, 6.4421665593981743, 2.0912595308116639e-021, +25, 6.4421665668487549, 2.0912591224302577e-021, +25, 7.2055878639221191, 9.8372734035261097e-023, +25, 7.2055878713726997, 9.8372708440629524e-023, +25, 7.9591367468237877, 5.7658750176114061e-024, +25, 7.9591367542743683, 5.7658733776591436e-024, +25, 8.7030665054917336, 4.1258272741964985e-025, +25, 8.7030665129423141, 4.1258258782473198e-025, +25, 9.4375757128000259, 3.5435416447318224e-026, +25, 9.4375757202506065, 3.5435412590635847e-026, +25, 10.162816897034645, 3.6008987404838187e-027, +25, 10.162816904485226, 3.6008987502968748e-027, +25, 10.878902837634087, 4.2764878951239796e-028, +25, 10.878902845084667, 4.2764868457382694e-028, +25, 11.58591116219759, 5.8725831294026438e-029, +25, 11.58591116964817, 5.872583554303668e-029, +25, 12.283887647092342, 9.2378193889837239e-030, +25, 12.283887654542923, 9.2378197873933138e-030, +25, 12.97284871339798, 1.6508371998843517e-030, +25, 12.97284872084856, 1.650837412798272e-030, +25, 13.652783133089542, 3.3266754235730111e-031, +25, 13.652783140540123, 3.3266744536286711e-031, +25, 14.323653288185596, 7.5089192296338788e-032, +25, 14.323653295636177, 7.5089195273493671e-032, +25, 14.985395908355713, 1.8869158708375887e-032, +25, 14.985395915806293, 1.8869156141367114e-032, +25, 15.637922637164593, 5.2491829350088782e-033, +25, 15.637922644615173, 5.2491824971659126e-033, +25, 16.281120285391808, 1.6081191935598747e-033, +25, 16.281120292842388, 1.608118845571321e-033, +25, 16.914851076900959, 5.3986271338461797e-034, +25, 16.91485108435154, 5.3986283194236148e-034, +25, 17.538952887058258, 1.9766512695275074e-034, +25, 17.538952894508839, 1.9766507896017455e-034, +25, 18.153239868581295, 7.8569686415203062e-035, +25, 18.153239876031876, 7.8569708046899769e-035, +25, 18.757503516972065, 3.3749866196468743e-035, +25, 18.757503524422646, 3.374985983250723e-035, +25, 19.351514972746372, 1.5594420539380395e-035, +25, 19.351514980196953, 1.5594416192490925e-035, +25, 19.935029000043869, 7.7158386293794966e-036, +25, 19.93502900749445, 7.7158392148375424e-036, +25, 20.507790975272655, 4.0656659632469917e-036, +25, 20.507790982723236, 4.0656647261416748e-036, +25, 21.069548606872559, 2.2711959500700407e-036, +25, 21.069548614323139, 2.2711951777269612e-036, +25, 21.62007087469101, 1.3353866143298436e-036, +25, 21.62007088214159, 1.3353860101843685e-036, +25, 22.159177884459496, 8.2143426189718226e-037, +25, 22.159177891910076, 8.2143413202705087e-037, +25, 22.68678567558527, 5.2648015059720179e-037, +25, 22.686785683035851, 5.2648001075197064e-037, +25, 23.202968575060368, 3.468211073462519e-037, +25, 23.202968582510948, 3.4682107310949544e-037, +25, 23.70803364366293, 2.3273599976356348e-037, +25, 23.70803365111351, 2.3273591213713725e-037, +25, 24.202582977712154, 1.5765602064246655e-037, +25, 24.202582985162735, 1.576559556129669e-037, +25, 24.687517486512661, 1.1088611117377277e-037, +25, 24.687517493963242, 1.1088604968432837e-037, +25, 25.16395078599453, 7.7583898454128553e-038, +25, 25.16395079344511, 7.7583939097854651e-038, +25, 25.627866134047508, 5.3068781900534944e-038, +25, 25.627866141498089, 5.3068810921059701e-038, +26, 0.78101654350757599, 5.8923908707209337e-008, +26, 0.78101655095815659, 5.8923821371534893e-008, +26, 1.6320968940854073, 1.236317730309333e-010, +26, 1.6320969015359879, 1.2363168158688363e-010, +26, 2.4678146317601204, 5.7429811601560071e-013, +26, 2.467814639210701, 5.7429765734855436e-013, +26, 3.2899207398295403, 4.734388742385331e-015, +26, 3.2899207472801208, 4.7343867559584461e-015, +26, 4.0996342152357101, 6.1272431600609502e-017, +26, 4.0996342226862907, 6.1272407979893011e-017, +26, 4.8978375121951103, 1.1506240642534423e-018, +26, 4.8978375196456909, 1.1506236852699587e-018, +26, 5.6851947978138924, 2.9671094902332928e-020, +26, 5.685194805264473, 2.9671085633439803e-020, +26, 6.4622200652956963, 1.0086511721536377e-021, +26, 6.4622200727462769, 1.0086507678940824e-021, +26, 7.2293184027075768, 4.3801061282054169e-023, +26, 7.2293184101581573, 4.3801050332411078e-023, +26, 7.9868123158812523, 2.3696799980087546e-024, +26, 7.9868123233318329, 2.3696791495984219e-024, +26, 8.7349593564867973, 1.5649197470426281e-025, +26, 8.7349593639373779, 1.5649197320553895e-025, +26, 9.4739642217755318, 1.2402917131745359e-026, +26, 9.4739642292261124, 1.2402913154591754e-026, +26, 10.2039874792099, 1.1629424955001513e-027, +26, 10.20398748666048, 1.1629425103997286e-027, +26, 10.925151742994785, 1.2742687180623173e-028, +26, 10.925151750445366, 1.2742686869329822e-028, +26, 11.637546353042126, 1.6143813265406585e-029, +26, 11.637546360492706, 1.6143813107433007e-029, +26, 12.341230750083923, 2.3428227604690718e-030, +26, 12.341230757534504, 2.3428227187060725e-030, +26, 13.036237008869648, 3.8625446674283068e-031, +26, 13.036237016320229, 3.8625439691448719e-031, +26, 13.722571700811386, 7.1813310277242243e-032, +26, 13.722571708261967, 7.1813308590609393e-032, +26, 14.400217205286026, 1.4957140381405686e-032, +26, 14.400217212736607, 1.4957142743655298e-032, +26, 15.069132648408413, 3.4688292162948178e-033, +26, 15.069132655858994, 3.4688284579266739e-033, +26, 15.729254551231861, 8.9084835395664626e-034, +26, 15.729254558682442, 8.908484325639754e-034, +26, 16.3804971575737, 2.5204945088761422e-034, +26, 16.380497165024281, 2.5204938761288704e-034, +26, 17.022752746939659, 7.8188945402045879e-035, +26, 17.02275275439024, 7.8188922746258055e-035, +26, 17.65589178353548, 2.6473364587263948e-035, +26, 17.655891790986061, 2.6473357716097579e-035, +26, 18.279763206839561, 9.7405122544829131e-036, +26, 18.279763214290142, 9.7405091647747447e-036, +26, 18.894194960594177, 3.878059833810667e-036, +26, 18.894194968044758, 3.8780594112881572e-036, +26, 19.498995013535023, 1.6636902562494894e-036, +26, 19.498995020985603, 1.6636907531659472e-036, +26, 20.093953281641006, 7.6577266090817481e-037, +26, 20.093953289091587, 7.657728188363079e-037, +26, 20.678845040500164, 3.7661248096741531e-037, +26, 20.678845047950745, 3.7661237372250638e-037, +26, 21.253436677157879, 1.9691052657118544e-037, +26, 21.253436684608459, 1.9691047946430182e-037, +26, 21.817495100200176, 1.0899858439496351e-037, +26, 21.817495107650757, 1.0899854262898754e-037, +26, 22.370802812278271, 6.3470096664624425e-038, +26, 22.370802819728851, 6.3470080713999366e-038, +26, 22.913181200623512, 3.86373588174236e-038, +26, 22.913181208074093, 3.8637351113998463e-038, +26, 23.444525294005871, 2.4535347310547519e-038, +26, 23.444525301456451, 2.4535359123032401e-038, +26, 23.964852377772331, 1.6049618186436992e-038, +26, 23.964852385222912, 1.604961872563914e-038, +26, 24.474362745881081, 1.0722943070757005e-038, +26, 24.474362753331661, 1.0722942325976742e-038, +26, 24.973499171435833, 7.2558350814098704e-039, +26, 24.973499178886414, 7.2558340329470219e-039, +26, 25.462974481284618, 5.0337622643621282e-039, +26, 25.462974488735199, 5.0337617320777135e-039, +26, 25.943732649087906, 3.5390684241286765e-039, +26, 25.943732656538486, 3.5390691209096449e-039, +26, 26.416851162910461, 2.4665037699450018e-039, +26, 26.416851170361042, 2.4665034955684909e-039, +26, 26.801410645246506, 1.1171525523613971e-039, +26, 26.801410652697086, 1.1171551092920132e-039, +27, 0.7828962579369545, 4.9861854667393399e-008, +27, 0.7828962653875351, 4.9861772593924402e-008, +27, 1.6355748474597931, 9.6921316479103525e-011, +27, 1.6355748549103737, 9.6921206864357132e-011, +27, 2.4731948226690292, 4.171211347524171e-013, +27, 2.4731948301196098, 4.1712091406116398e-013, +27, 3.2974838986992836, 3.1856718158208548e-015, +27, 3.2974839061498642, 3.1856696336218403e-015, +27, 4.1096459552645683, 3.8192029014720663e-017, +27, 4.1096459627151489, 3.8192010297992792e-017, +27, 4.9105536565184593, 6.6429667302540135e-019, +27, 4.9105536639690399, 6.6429652717397208e-019, +27, 5.7008651793003082, 1.5864616200237458e-020, +27, 5.7008651867508888, 1.5864611294551399e-020, +27, 6.4810914397239685, 4.993999498145391e-022, +27, 6.4810914471745491, 4.9939979049271363e-022, +27, 7.2516367882490158, 2.0079266330070849e-023, +27, 7.2516367956995964, 2.0079265308291086e-023, +27, 8.0128250047564507, 1.0056680741144098e-024, +27, 8.0128250122070312, 1.0056677361707529e-024, +27, 8.7649167329072952, 6.1476317533215932e-026, +27, 8.7649167403578758, 6.1476309156933445e-026, +27, 9.5081214383244514, 4.5096613837282808e-027, +27, 9.508121445775032, 4.5096604070043352e-027, +27, 10.242606043815613, 3.9132924912256924e-028, +27, 10.242606051266193, 3.9132926019691446e-028, +27, 10.96850112080574, 3.9680374563073656e-029, +27, 10.968501128256321, 3.968037549032286e-029, +27, 11.685905538499355, 4.6518641224931443e-030, +27, 11.685905545949936, 4.6518631300160416e-030, +27, 12.394889906048775, 6.2467209675851883e-031, +27, 12.394889913499355, 6.2467197889832523e-031, +27, 13.095499135553837, 9.5296302920980662e-032, +27, 13.095499143004417, 9.5296301328881049e-032, +27, 13.787754379212856, 1.6394978658915808e-032, +27, 13.787754386663437, 1.6394979205807897e-032, +27, 14.471654459834099, 3.1600211613408551e-033, +27, 14.471654467284679, 3.1600209693232782e-033, +27, 15.147176899015903, 6.7828954814670378e-034, +27, 15.147176906466484, 6.7828945671314482e-034, +27, 15.81427863240242, 1.6125447486417395e-034, +27, 15.814278639853001, 1.6125444345876133e-034, +27, 16.472896493971348, 4.2246556605945897e-035, +27, 16.472896501421928, 4.224654227049247e-035, +27, 17.122947536408901, 1.2139966311739369e-035, +27, 17.122947543859482, 1.2139966298630524e-035, +27, 17.764329209923744, 3.8095779223206078e-036, +27, 17.764329217374325, 3.8095779252456187e-036, +27, 18.396919578313828, 1.3000203710965374e-036, +27, 18.396919585764408, 1.3000203411711264e-036, +27, 19.020577564835548, 4.8049120367747199e-037, +27, 19.020577572286129, 4.8049124355340798e-037, +27, 19.635143436491489, 1.9158924823061778e-037, +27, 19.63514344394207, 1.9158920386648308e-037, +27, 20.240439757704735, 8.2093208358169539e-038, +27, 20.240439765155315, 8.2093222197429644e-038, +27, 20.836273021996021, 3.7650963780981519e-038, +27, 20.836273029446602, 3.7650975525688663e-038, +27, 21.422436565160751, 1.8412740319560743e-038, +27, 21.422436572611332, 1.8412734834107893e-038, +27, 21.998715363442898, 9.5568938496580513e-039, +27, 21.998715370893478, 9.5568962750049465e-039, +27, 22.564893670380116, 5.2444711828702124e-039, +27, 22.564893677830696, 5.2444725699857754e-039, +27, 23.120767138898373, 3.0256331670909385e-039, +27, 23.120767146348953, 3.0256324528122128e-039, +27, 23.666161254048347, 1.8245360187243205e-039, +27, 23.666161261498928, 1.8245363450061449e-039, +27, 24.200958535075188, 1.1470036575842657e-039, +27, 24.200958542525768, 1.1470033205632092e-039, +27, 24.725136809051037, 7.4468116835290912e-040, +27, 24.725136816501617, 7.4468134793516934e-040, +27, 25.238818168640137, 4.9485796130614579e-040, +27, 25.238818176090717, 4.9485778772589032e-040, +27, 25.742321841418743, 3.3399923581817735e-040, +27, 25.742321848869324, 3.3399911124650134e-040, +27, 26.236201457679272, 2.2838209417828281e-040, +27, 26.236201465129852, 2.2838217806321604e-040, +27, 26.721238203346729, 1.6104454076256336e-040, +27, 26.72123821079731, 1.6104457017695957e-040, +27, 27.198375716805458, 1.12895575803922e-040, +27, 27.198375724256039, 1.1289556733584685e-040, +27, 27.669778347015381, 7.8496301393215855e-041, +27, 27.669778354465961, 7.8496341262896801e-041, +27, 27.884223878383636, 4.4309665223873591e-041, +27, 27.884223885834217, 4.4309591849200503e-041, +28, 0.78467844426631927, 4.2438470083140721e-008, +28, 0.78467845171689987, 4.2438393278981791e-008, +28, 1.6388683915138245, 7.6621569710548971e-011, +28, 1.6388683989644051, 7.66215089154498e-011, +28, 2.4782853201031685, 3.0631204478184193e-013, +28, 2.4782853275537491, 3.063118924040777e-013, +28, 3.304634802043438, 2.1729815422346648e-015, +28, 3.3046348094940186, 2.1729799923068305e-015, +28, 4.1191061362624168, 2.4196250779813722e-017, +28, 4.1191061437129974, 2.4196239816772689e-017, +28, 4.9225624054670334, 3.9085656395735408e-019, +28, 4.922562412917614, 3.9085649025210167e-019, +28, 5.7156557217240334, 8.6680273869165024e-021, +28, 5.715655729174614, 8.6680236478512346e-021, +28, 6.498893603682518, 2.5335387999951474e-022, +28, 6.4988936111330986, 2.5335376908522942e-022, +28, 7.2726791352033615, 9.4573144592121954e-024, +28, 7.2726791426539421, 9.4573116298964195e-024, +28, 8.0373366698622704, 4.3971230185116881e-025, +28, 8.037336677312851, 4.3971227534536684e-025, +28, 8.793128989636898, 2.4950063652246191e-026, +28, 8.7931289970874786, 2.495005720678091e-026, +28, 9.5402692407369614, 1.6986980617997022e-027, +28, 9.540269248187542, 1.6986976051079919e-027, +28, 10.278929390013218, 1.368000853859253e-028, +28, 10.278929397463799, 1.3680004892213298e-028, +28, 11.009246453642845, 1.2872419602896367e-029, +28, 11.009246461093426, 1.2872420187471339e-029, +28, 11.731327079236507, 1.4003201763391476e-030, +28, 11.731327086687088, 1.4003202386076777e-030, +28, 12.445251040160656, 1.7448255734165301e-031, +28, 12.445251047611237, 1.7448253583893487e-031, +28, 13.151073843240738, 2.4698393595556993e-032, +28, 13.151073850691319, 2.4698391161370222e-032, +28, 13.848828695714474, 3.9427669364651789e-033, +28, 13.848828703165054, 3.9427660690914164e-033, +28, 14.538528017699718, 7.0517495293252521e-034, +28, 14.538528025150299, 7.0517474992045073e-034, +28, 15.22016453742981, 1.4046733706426603e-034, +28, 15.22016454488039, 1.4046729721237711e-034, +28, 15.893712103366852, 3.0994444806456431e-035, +28, 15.893712110817432, 3.0994449626913169e-035, +28, 16.55912622064352, 7.5380952232932651e-036, +28, 16.559126228094101, 7.5380932219859205e-036, +28, 17.216344498097897, 2.0114378107354203e-036, +28, 17.216344505548477, 2.0114379656122684e-036, +28, 17.865286819636822, 5.8633939940250315e-037, +28, 17.865286827087402, 5.8633946299343831e-037, +28, 18.505855575203896, 1.8596224339761576e-037, +28, 18.505855582654476, 1.8596221870214534e-037, +28, 19.137935824692249, 6.3922092248869744e-038, +28, 19.13793583214283, 6.3922102380482483e-038, +28, 19.761395521461964, 2.3724862433709197e-038, +28, 19.761395528912544, 2.3724866454052567e-038, +28, 20.376085996627808, 9.4731318337289952e-039, +28, 20.376086004078388, 9.4731287775953353e-039, +28, 20.981842800974846, 4.0545371346860406e-039, +28, 20.981842808425426, 4.0545370535552068e-039, +28, 21.578487128019333, 1.8533283507255836e-039, +28, 21.578487135469913, 1.853328817895879e-039, +28, 22.165828302502632, 9.0155863853882353e-040, +28, 22.165828309953213, 9.0155831427237625e-040, +28, 22.743667811155319, 4.6472893319487125e-040, +28, 22.7436678186059, 4.6472889307429114e-040, +28, 23.311805583536625, 2.5293602604427438e-040, +28, 23.311805590987206, 2.5293596848335514e-040, +28, 23.870049826800823, 1.4463087106544672e-040, +28, 23.870049834251404, 1.4463085194116285e-040, +28, 24.418231755495071, 8.641896329274563e-041, +28, 24.418231762945652, 8.6418996111656845e-041, +28, 24.956227175891399, 5.3786841208254478e-041, +28, 24.95622718334198, 5.378682136136815e-041, +28, 25.483986794948578, 3.4648144680023666e-041, +28, 25.483986802399158, 3.4648129601794969e-041, +28, 26.001575656235218, 2.2884086968613662e-041, +28, 26.001575663685799, 2.2884098625776109e-041, +28, 26.509218297898769, 1.5387898607295863e-041, +28, 26.50921830534935, 1.538789924506611e-041, +28, 27.00733794271946, 1.0458893902132325e-041, +28, 27.00733795017004, 1.0458899705307257e-041, +28, 27.4965685531497, 7.317848728543107e-042, +28, 27.496568560600281, 7.3178520005717001e-042, +28, 27.977721095085144, 5.1513043977723732e-042, +28, 27.977721102535725, 5.1513042258958866e-042, +28, 28.451707921922207, 3.5986164377315787e-042, +28, 28.451707929372787, 3.5986160057693314e-042, +29, 0.78637154400348663, 3.6315909083995129e-008, +29, 0.78637155145406723, 3.6315849334616369e-008, +29, 1.6419936791062355, 6.1049645545974547e-011, +29, 1.6419936865568161, 6.1049599294982487e-011, +29, 2.4831117615103722, 2.2726035573991162e-013, +29, 2.4831117689609528, 2.2726023881733654e-013, +29, 3.3114102259278297, 1.5011780867764562e-015, +29, 3.3114102333784103, 1.5011775587872939e-015, +29, 4.128064326941967, 1.5563805350068021e-017, +29, 4.1280643343925476, 1.5563800665439041e-017, +29, 4.9339278042316437, 2.3406905946198134e-019, +29, 4.9339278116822243, 2.3406896430597371e-019, +29, 5.7296467050909996, 4.8324621843737061e-021, +29, 5.7296467125415802, 4.8324604821555049e-021, +29, 6.5157249048352242, 1.314795562058049e-022, +29, 6.5157249122858047, 1.3147952115386097e-022, +29, 7.2925638258457184, 4.5681547645026199e-024, +29, 7.292563833296299, 4.5681541042570898e-024, +29, 8.0604878067970276, 1.9767148584973311e-025, +29, 8.0604878142476082, 1.9767144437084469e-025, +29, 8.8197610825300217, 1.0437840229618024e-026, +29, 8.8197610899806023, 1.0437836457111727e-026, +29, 9.5705995559692383, 6.6127541570083993e-028, +29, 9.5705995634198189, 6.6127525803998794e-028, +29, 10.313179194927216, 4.9550353823480331e-029, +29, 10.313179202377796, 4.9550344472793234e-029, +29, 11.047642216086388, 4.3379652668743748e-030, +29, 11.047642223536968, 4.3379651694905502e-030, +29, 11.77410165220499, 4.3903098563318958e-031, +29, 11.774101659655571, 4.3903087396488023e-031, +29, 12.492644853889942, 5.0891392311082294e-032, +29, 12.492644861340523, 5.089138080132273e-032, +29, 13.203336097300053, 6.7015567871931459e-033, +29, 13.203336104750633, 6.7015574012559967e-033, +29, 13.906218603253365, 9.9522699683293545e-034, +29, 13.906218610703945, 9.9522699561603004e-034, +29, 14.60131610929966, 1.6559310130268636e-034, +29, 14.60131611675024, 1.6559308877250499e-034, +29, 15.28863400965929, 3.0688012602367554e-035, +29, 15.288634017109871, 3.0688008505595191e-035, +29, 15.968160234391689, 6.3003656761785947e-036, +29, 15.96816024184227, 6.300365157267352e-036, +29, 16.639865875244141, 1.425912288294408e-036, +29, 16.639865882694721, 1.425911844482608e-036, +29, 17.303705655038357, 3.5413918087008817e-037, +29, 17.303705662488937, 3.5413910585270221e-037, +29, 17.959618203341961, 9.6110663827236623e-038, +29, 17.959618210792542, 9.6110639887579061e-038, +29, 18.607526287436485, 2.8389759994471709e-038, +29, 18.607526294887066, 2.8389752688919641e-038, +29, 19.247336961328983, 9.0931089735817269e-039, +29, 19.247336968779564, 9.0931107476948825e-039, +29, 19.878941707313061, 3.1467556490433912e-039, +29, 19.878941714763641, 3.1467564127571162e-039, +29, 20.502216704189777, 1.1724748656710215e-039, +29, 20.502216711640358, 1.1724746734027557e-039, +29, 21.117023251950741, 4.6876364663697041e-040, +29, 21.117023259401321, 4.6876364357803892e-040, +29, 21.723208487033844, 2.0042123089344851e-040, +29, 21.723208494484425, 2.0042116411036911e-040, +29, 22.320606715977192, 9.132472556056144e-041, +29, 22.320606723427773, 9.1324737655785673e-041, +29, 22.909041479229927, 4.4204627633406315e-041, +29, 22.909041486680508, 4.420462690830891e-041, +29, 23.488328985869884, 2.2638612067742748e-041, +29, 23.488328993320465, 2.2638616763927321e-041, +29, 24.05828333646059, 1.2225551251648693e-041, +29, 24.058283343911171, 1.2225553197479533e-041, +29, 24.618724562227726, 6.9314021088591364e-042, +29, 24.618724569678307, 6.9314047935940562e-042, +29, 25.169490531086922, 4.1049308418651103e-042, +29, 25.169490538537502, 4.1049319553758314e-042, +29, 25.710454262793064, 2.5298050928083053e-042, +29, 25.710454270243645, 2.5298056900518227e-042, +29, 26.241548083722591, 1.6166462380689568e-042, +29, 26.241548091173172, 1.6166465098434285e-042, +29, 26.762795478105545, 1.0606841937797943e-042, +29, 26.762795485556126, 1.0606843404549322e-042, +29, 27.274348974227905, 7.0992566551399511e-043, +29, 27.274348981678486, 7.0992546682756672e-043, +29, 27.776527158915997, 4.8148903392572901e-043, +29, 27.776527166366577, 4.814888042092614e-043, +29, 28.269836388528347, 3.3234515341900158e-043, +29, 28.269836395978928, 3.3234500791670542e-043, +29, 28.754959724843502, 2.3456576866672306e-043, +29, 28.754959732294083, 2.345656656614369e-043, +29, 29.232707068324089, 1.6470684285437321e-043, +29, 29.23270707577467, 1.6470683545256373e-043, +29, 29.70374021679163, 1.14547675702381e-043, +29, 29.70374022424221, 1.1454765601759464e-043, +30, 0.7879829928278923, 3.1234103821482427e-008, +30, 0.7879830002784729, 3.1234044655401994e-008, +30, 1.6449649482965469, 4.9000015491257048e-011, +30, 1.6449649557471275, 4.8999963821072772e-011, +30, 2.4876966997981071, 1.7023669931328061e-013, +30, 2.4876967072486877, 1.7023657129354393e-013, +30, 3.3178424835205078, 1.0494761982366968e-015, +30, 3.3178424909710884, 1.0494757357860962e-015, +30, 4.1365640535950661, 1.0154249700920638e-017, +30, 4.1365640610456467, 1.0154243875133412e-017, +30, 4.9447060599923134, 1.4250864555511693e-019, +30, 4.944706067442894, 1.4250858796996163e-019, +30, 5.7429084852337837, 2.7453691120619369e-021, +30, 5.7429084926843643, 2.7453685866311988e-021, +30, 6.5316714197397232, 6.9693659068680088e-023, +30, 6.5316714271903038, 6.9693629187270163e-023, +30, 7.3113943338394165, 2.2591471868696091e-024, +30, 7.3113943412899971, 2.2591466479292196e-024, +30, 8.0824010968208313, 9.1197383000971079e-026, +30, 8.0824011042714119, 9.1197355380522927e-026, +30, 8.8449568077921867, 4.4921066968594634e-027, +30, 8.8449568152427673, 4.4921064406150814e-027, +30, 9.5992793887853622, 2.6545531428409782e-028, +30, 9.5992793962359428, 2.6545522470546947e-028, +30, 10.34554798156023, 1.855221838168487e-029, +30, 10.345547989010811, 1.8552214020399549e-029, +30, 11.083908997476101, 1.5147783374462689e-030, +30, 11.083909004926682, 1.5147781122476647e-030, +30, 11.81448071449995, 1.4297164287403578e-031, +30, 11.814480721950531, 1.429716050915216e-031, +30, 12.537356749176979, 1.5455160104219774e-032, +30, 12.53735675662756, 1.5455160199328339e-032, +30, 13.252608671784401, 1.8978775176433715e-033, +30, 13.252608679234982, 1.8978774707164247e-033, +30, 13.960288092494011, 2.6282911950633352e-034, +30, 13.960288099944592, 2.6282913708927645e-034, +30, 14.660428203642368, 4.0780899601901608e-035, +30, 14.660428211092949, 4.0780894770882105e-035, +30, 15.353045016527176, 7.0479243716573658e-036, +30, 15.353045023977757, 7.0479222548237397e-036, +30, 16.038138270378113, 1.3494709199819255e-036, +30, 16.038138277828693, 1.3494705517069979e-036, +30, 16.715692117810249, 2.8486491673345358e-037, +30, 16.71569212526083, 2.8486483929154767e-037, +30, 17.385675646364689, 6.5998055420207975e-038, +30, 17.385675653815269, 6.5998062646129257e-038, +30, 18.048043206334114, 1.6711936241018928e-038, +30, 18.048043213784695, 1.6711932368686648e-038, +30, 18.702734716236591, 4.6071433653083805e-039, +30, 18.702734723687172, 4.6071443081395363e-039, +30, 19.349675759673119, 1.3776916161772679e-039, +30, 19.349675767123699, 1.3776916401455473e-039, +30, 19.988777793943882, 4.4532108875418354e-040, +30, 19.988777801394463, 4.4532114573536834e-040, +30, 20.619938254356384, 1.5507563718868067e-040, +30, 20.619938261806965, 1.5507566883583332e-040, +30, 21.243040800094604, 5.7990312184030671e-041, +30, 21.243040807545185, 5.7990304989845352e-041, +30, 21.857955724000931, 2.3212797494554108e-041, +30, 21.857955731451511, 2.3212803480860163e-041, +30, 22.464540585875511, 9.914865440882635e-042, +30, 22.464540593326092, 9.9148662773812494e-042, +30, 23.062641389667988, 4.5045190716090583e-042, +30, 23.062641397118568, 4.5045174791143897e-042, +30, 23.652094401419163, 2.1701628812569051e-042, +30, 23.652094408869743, 2.1701625772121853e-042, +30, 24.232729002833366, 1.1046043114766288e-042, +30, 24.232729010283947, 1.1046045034064885e-042, +30, 24.804372116923332, 5.9211173400922859e-043, +30, 24.804372124373913, 5.9211190991234153e-043, +30, 25.366854824125767, 3.3298155214419811e-043, +30, 25.366854831576347, 3.3298157358067105e-043, +30, 25.92002210021019, 1.9551128692966943e-043, +30, 25.92002210766077, 1.9551123692323681e-043, +30, 26.463746801018715, 1.1933006750773454e-043, +30, 26.463746808469296, 1.1933004727347112e-043, +30, 26.997949115931988, 7.5643757950805542e-044, +30, 26.997949123382568, 7.5643761045987683e-044, +30, 27.522622361779213, 4.9284040353068413e-044, +30, 27.522622369229794, 4.9284056246758231e-044, +30, 28.037864476442337, 3.2810162604333193e-044, +30, 28.037864483892918, 3.281017845647255e-044, +30, 28.543911211192608, 2.2181628671749676e-044, +30, 28.543911218643188, 2.218162484652318e-044, +30, 29.041161552071571, 1.5134037301717584e-044, +30, 29.041161559522152, 1.5134029110911047e-044, +30, 29.530181311070919, 1.0667420585863651e-044, +30, 29.5301813185215, 1.0667417522137867e-044, +30, 30.011674650013447, 7.5174774420740806e-045, +30, 30.011674657464027, 7.5174742900736671e-045, +30, 30.486428417265415, 5.2621270182135051e-045, +30, 30.486428424715996, 5.262130311093599e-045, +30, 30.939444169402122, 3.5015139512069607e-045, +30, 30.939444176852703, 3.5015112710245708e-045, +31, 0.78951938450336456, 2.6990963852982276e-008, +31, 0.78951939195394516, 2.6990901272098622e-008, +31, 1.6477948054671288, 3.9599591893838782e-011, +31, 1.6477948129177094, 3.9599558875077027e-011, +31, 2.4920600801706314, 1.2867416450803074e-013, +31, 2.492060087621212, 1.286740858923318e-013, +31, 3.3239601328969002, 7.4191337236762968e-016, +31, 3.3239601403474808, 7.4191298658981141e-016, +31, 4.144643746316433, 6.7136115607620136e-018, +31, 4.1446437537670135, 6.7136080734499562e-018, +31, 4.9549467116594315, 8.8116416572145598e-020, +31, 4.9549467191100121, 8.8116378746161626e-020, +31, 5.7555030211806297, 1.5874468287337354e-021, +31, 5.7555030286312103, 1.5874462991137669e-021, +31, 6.5468088984489441, 3.7683180579985163e-023, +31, 6.5468089058995247, 3.7683164558120959e-023, +31, 7.3292616009712219, 1.1421590109206418e-024, +31, 7.3292616084218025, 1.1421585299332504e-024, +31, 8.103184200823307, 4.3108518074612864e-026, +31, 8.1031842082738876, 4.3108510892707748e-026, +31, 8.8688421621918678, 1.9851855023091017e-027, +31, 8.8688421696424484, 1.9851853532161421e-027, +31, 9.6264548823237419, 1.0966928714056398e-028, +31, 9.6264548897743225, 1.0966926721759533e-028, +31, 10.376203939318657, 7.164836764783927e-030, +31, 10.376203946769238, 7.1648343154883914e-030, +31, 11.118239149451256, 5.4683058705610656e-031, +31, 11.118239156901836, 5.4683043353071719e-031, +31, 11.8526830971241, 4.8242112495562322e-032, +31, 11.85268310457468, 4.8242113495352988e-032, +31, 12.579634577035904, 4.8742340289959263e-033, +31, 12.579634584486485, 4.8742330295078644e-033, +31, 13.299171291291714, 5.5942948410353604e-034, +31, 13.299171298742294, 5.5942937409224875e-034, +31, 14.011351861059666, 7.2408340380396581e-035, +31, 14.011351868510246, 7.2408326912367206e-035, +31, 14.716217450797558, 1.0500501579246543e-035, +31, 14.716217458248138, 1.0500500363643936e-035, +31, 15.413793005049229, 1.6961373883454169e-036, +31, 15.413793012499809, 1.6961372726275582e-036, +31, 16.104088209569454, 3.0354866582877075e-037, +31, 16.104088217020035, 3.0354856266520219e-037, +31, 16.787098243832588, 5.9896173771901093e-038, +31, 16.787098251283169, 5.98961535516797e-038, +31, 17.462804310023785, 1.2972746518568634e-038, +31, 17.462804317474365, 1.2972745309510283e-038, +31, 18.13117404282093, 3.0713680138571644e-039, +31, 18.131174050271511, 3.0713676965074795e-039, +31, 18.79216181486845, 7.9182263243406493e-040, +31, 18.792161822319031, 7.9182241350107358e-040, +31, 19.445708937942982, 2.214898087434925e-040, +31, 19.445708945393562, 2.2148980677402555e-040, +31, 20.091743782162666, 6.6993154618323218e-041, +31, 20.091743789613247, 6.6993135377084829e-041, +31, 20.730181947350502, 2.1839810764001286e-041, +31, 20.730181954801083, 2.1839807962981238e-041, +31, 21.360926359891891, 7.6498865481473596e-042, +31, 21.360926367342472, 7.6498850691523407e-042, +31, 21.983867526054382, 2.8703402503431693e-042, +31, 21.983867533504963, 2.8703404559755345e-042, +31, 22.598883867263794, 1.1502498454193117e-042, +31, 22.598883874714375, 1.1502498916466649e-042, +31, 23.205842353403568, 4.9084725935443196e-043, +31, 23.205842360854149, 4.9084710329663892e-043, +31, 23.80459950864315, 2.2238235774505732e-043, +31, 23.804599516093731, 2.2238237880748328e-043, +31, 24.395002961158752, 1.0666581061637025e-043, +31, 24.395002968609333, 1.0666576688114463e-043, +31, 24.976893968880177, 5.3977921159553397e-044, +31, 24.976893976330757, 5.3977934865920802e-044, +31, 25.550111055374146, 2.8731051700509201e-044, +31, 25.550111062824726, 2.8731044277207976e-044, +31, 26.114495605230331, 1.6031969299858829e-044, +31, 26.114495612680912, 1.6031970042652873e-044, +31, 26.669899813830853, 9.3355015180719599e-045, +31, 26.669899821281433, 9.3355052705843679e-045, +31, 27.216198123991489, 5.6495965443312072e-045, +31, 27.21619813144207, 5.6495939839503296e-045, +31, 27.753303058445454, 3.5492321895997083e-045, +31, 27.753303065896034, 3.5492321163912673e-045, +31, 28.281186141073704, 2.2957811874765475e-045, +31, 28.281186148524284, 2.2957814583395176e-045, +31, 28.799904033541679, 1.5194259395681735e-045, +31, 28.79990404099226, 1.5194267112625272e-045, +31, 29.309627436101437, 1.0230813499247931e-045, +31, 29.309627443552017, 1.0230809924412674e-045, +31, 29.810666806995869, 6.9676223029316235e-046, +31, 29.810666814446449, 6.9676192007503771e-046, +31, 30.303484387695789, 4.8488184998921204e-046, +31, 30.30348439514637, 4.8488172078839344e-046, +31, 30.788682028651237, 3.4250229581297795e-046, +31, 30.788682036101818, 3.4250250734052242e-046, +31, 31.266962468624115, 2.4084133971405881e-046, +31, 31.266962476074696, 2.4084125559476293e-046, +31, 31.73910990357399, 1.6796117435938392e-046, +31, 31.73910991102457, 1.679611553823398e-046, +32, 0.79098659008741379, 2.3428195699417537e-008, +32, 0.79098659753799438, 2.3428153358786678e-008, +32, 1.6504944264888763, 3.2209746415594332e-011, +32, 1.6504944339394569, 3.220970087503767e-011, +32, 2.496219590306282, 9.8084828719793923e-014, +32, 2.4962195977568626, 9.8084762239900993e-014, +32, 3.3297884985804558, 5.3000509925270763e-016, +32, 3.3297885060310364, 5.3000487530063089e-016, +32, 4.152337446808815, 4.4945824866210701e-018, +32, 4.1523374542593956, 4.4945810140566077e-018, +32, 4.9646936282515526, 5.5281595989002857e-020, +32, 4.9646936357021332, 5.5281565203257855e-020, +32, 5.7674851417541504, 9.332409158236809e-022, +32, 5.767485149204731, 9.3324053526450437e-022, +32, 6.5612042769789696, 2.0758269859270062e-023, +32, 6.5612042844295502, 2.0758259829402165e-023, +32, 7.3462459221482277, 5.895162008888518e-025, +32, 7.3462459295988083, 5.8951601605246428e-025, +32, 8.1229320466518402, 2.0846533511721846e-026, +32, 8.1229320541024208, 2.0846528892286505e-026, +32, 8.8915281295776367, 8.9939213820927554e-028, +32, 8.8915281370282173, 8.9939197373278422e-028, +32, 9.6522545516490936, 4.6546437360965095e-029, +32, 9.6522545590996742, 4.6546426636937451e-029, +32, 10.405294768512249, 2.8486464379340495e-030, +32, 10.40529477596283, 2.8486455621645871e-030, +32, 11.150801315903664, 2.0365499436102757e-031, +32, 11.150801323354244, 2.0365494007674272e-031, +32, 11.888900309801102, 1.682907109838634e-032, +32, 11.888900317251682, 1.6829069079598241e-032, +32, 12.619694881141186, 1.5926342764153439e-033, +32, 12.619694888591766, 1.592634174405931e-033, +32, 13.34326783567667, 1.7120603159420472e-034, +32, 13.343267843127251, 1.7120602511528744e-034, +32, 14.059683710336685, 2.075481423520178e-035, +32, 14.059683717787266, 2.075480991830116e-035, +32, 14.768990404903889, 2.8189962905017707e-036, +32, 14.768990412354469, 2.818995942400197e-036, +32, 15.471220426261425, 4.2648503825577588e-037, +32, 15.471220433712006, 4.2648499164953187e-037, +32, 16.166391901671886, 7.1489312549880753e-038, +32, 16.166391909122467, 7.1489309687917951e-038, +32, 16.854509338736534, 1.3213054825449378e-038, +32, 16.854509346187115, 1.3213054922746664e-038, +32, 17.535564221441746, 2.6807748064712788e-039, +32, 17.535564228892326, 2.6807748199492672e-039, +32, 18.209535457193851, 5.9460888344062753e-040, +32, 18.209535464644432, 5.94608895781776e-040, +32, 18.87638970464468, 1.4363587657615266e-040, +32, 18.876389712095261, 1.4363589517907267e-040, +32, 19.536081604659557, 3.765393350640845e-041, +32, 19.536081612110138, 3.7653931802714443e-041, +32, 20.188553966581821, 1.0676300156436359e-041, +32, 20.188553974032402, 1.067629917232314e-041, +32, 20.833737879991531, 3.263757534857454e-042, +32, 20.833737887442112, 3.2637579615392064e-042, +32, 21.471552819013596, 1.0724762195516768e-042, +32, 21.471552826464176, 1.072475891341324e-042, +32, 22.101906821131706, 3.777144305210756e-043, +32, 22.101906828582287, 3.7771444342513115e-043, +32, 22.724696628749371, 1.4217203788681964e-043, +32, 22.724696636199951, 1.4217200228446998e-043, +32, 23.339808091521263, 5.703322551588163e-044, +32, 23.339808098971844, 5.7033226900296373e-044, +32, 23.947116665542126, 2.4316437058578012e-044, +32, 23.947116672992706, 2.431643496160822e-044, +32, 24.546488344669342, 1.0987930055297978e-044, +32, 24.546488352119923, 1.098793076553521e-044, +32, 25.137781016528606, 5.2484169483265025e-045, +32, 25.137781023979187, 5.2484155226682376e-045, +32, 25.720846608281136, 2.6413713577457922e-045, +32, 25.720846615731716, 2.6413705700550837e-045, +32, 26.295534215867519, 1.3965382507957447e-045, +32, 26.2955342233181, 1.3965377603185929e-045, +32, 26.861694745719433, 7.7349160811880277e-046, +32, 26.861694753170013, 7.7349151441627e-046, +32, 27.419187560677528, 4.4682520650157615e-046, +32, 27.419187568128109, 4.4682538523866773e-046, +32, 27.967889867722988, 2.6819888403852565e-046, +32, 27.967889875173569, 2.6819897728379184e-046, +32, 28.507709659636021, 1.6698136917664954e-046, +32, 28.507709667086601, 1.6698129992594366e-046, +32, 29.038602896034718, 1.0721878956432574e-046, +32, 29.038602903485298, 1.0721875356655942e-046, +32, 29.560595072805882, 7.051821086699878e-047, +32, 29.560595080256462, 7.0518182781581043e-047, +32, 30.073806069791317, 4.7259218308968253e-047, +32, 30.073806077241898, 4.7259227603342754e-047, +32, 30.578474305570126, 3.209662989709749e-047, +32, 30.578474313020706, 3.2096634823719178e-047, +32, 31.074972994625568, 2.2043194970557608e-047, +32, 31.074973002076149, 2.2043198986132966e-047, +32, 31.563809163868427, 1.5587084684342884e-047, +32, 31.563809171319008, 1.5587077448629143e-047, +32, 32.045599952340126, 1.0995759280252866e-047, +32, 32.045599959790707, 1.0995758350300892e-047, +32, 32.521030142903328, 7.709762090925553e-048, +32, 32.521030150353909, 7.7097590622875819e-048, +33, 0.79238983243703842, 2.042106061094407e-008, +33, 0.79238983988761902, 2.0421020445651014e-008, +33, 1.6530738100409508, 2.6358450934546795e-011, +33, 1.6530738174915314, 2.635841919126038e-011, +33, 2.5001910030841827, 7.5364817160196323e-014, +33, 2.5001910105347633, 7.5364760748258798e-014, +33, 3.3353501185774803, 3.8237192966188636e-016, +33, 3.3353501260280609, 3.8237162369967308e-016, +33, 4.1596754416823387, 3.0445800511517908e-018, +33, 4.1596754491329193, 3.0445787674974564e-018, +33, 4.9739858210086823, 3.515919024039416e-020, +33, 4.9739858284592628, 3.5159171374646909e-020, +33, 5.7789035513997078, 5.5725899313574696e-022, +33, 5.7789035588502884, 5.5725880635319834e-022, +33, 6.5749169737100601, 1.1637027161635936e-023, +33, 6.5749169811606407, 1.1637021424764075e-023, +33, 7.3624184802174568, 3.1025238187243698e-025, +33, 7.3624184876680374, 3.1025225685285597e-025, +33, 8.1417287290096283, 1.0299156448677693e-026, +33, 8.1417287364602089, 1.0299152761838333e-026, +33, 8.9131129011511803, 4.1710447383740305e-028, +33, 8.9131129086017609, 4.1710436855039434e-028, +33, 9.6767919734120369, 2.0262351044072931e-029, +33, 9.6767919808626175, 2.0262350205955798e-029, +33, 10.432950802147388, 1.1639387550487137e-030, +33, 10.432950809597969, 1.1639386971982789e-030, +33, 11.181744091212749, 7.8101004107994773e-032, +33, 11.18174409866333, 7.8100993240538107e-032, +33, 11.923300854861736, 6.057244317232184e-033, +33, 11.923300862312317, 6.0572438899922103e-033, +33, 12.6577278226614, 5.37984912688152e-034, +33, 12.65772783011198, 5.3798488576528694e-034, +33, 13.385112091898918, 5.4275123456899329e-035, +33, 13.385112099349499, 5.4275107204683884e-035, +33, 14.105523213744164, 6.1747593213329447e-036, +33, 14.105523221194744, 6.174759584448652e-036, +33, 14.819014765322208, 7.8706673148814995e-037, +33, 14.819014772772789, 7.8706658404194138e-037, +33, 15.525625705718994, 1.1174748948810545e-037, +33, 15.525625713169575, 1.1174747454074421e-037, +33, 16.225381337106228, 1.7579206924880998e-038, +33, 16.225381344556808, 1.7579206925033476e-038, +33, 16.918294116854668, 3.0493015445964011e-039, +33, 16.918294124305248, 3.0493005632386758e-039, +33, 17.604364313185215, 5.8065726456748308e-040, +33, 17.604364320635796, 5.8065735081689733e-040, +33, 18.283580414950848, 1.2088940527454202e-040, +33, 18.283580422401428, 1.2088939296397679e-040, +33, 18.955919578671455, 2.7413543307825419e-041, +33, 18.955919586122036, 2.7413546854069123e-041, +33, 19.621347822248936, 6.7471885014535665e-042, +33, 19.621347829699516, 6.7471864084760131e-042, +33, 20.279820293188095, 1.7965045060899062e-042, +33, 20.279820300638676, 1.796504759041087e-042, +33, 20.931281328201294, 5.158585136120737e-043, +33, 20.931281335651875, 5.1585840276484414e-043, +33, 21.575664646923542, 1.5927422905564557e-043, +33, 21.575664654374123, 1.5927419041709561e-043, +33, 22.212893404066563, 5.2728323500442264e-044, +33, 22.212893411517143, 5.272833301596633e-044, +33, 22.842880316078663, 1.8665508074309968e-044, +33, 22.842880323529243, 1.8665503929597308e-044, +33, 23.465527907013893, 7.0465510247547303e-045, +33, 23.465527914464474, 7.0465525196870561e-045, +33, 24.080728746950626, 2.8295466700413958e-045, +33, 24.080728754401207, 2.8295463117518774e-045, +33, 24.688366025686264, 1.2053907748860486e-045, +33, 24.688366033136845, 1.2053907797297697e-045, +33, 25.288314290344715, 5.4333713658348499e-046, +33, 25.288314297795296, 5.4333707575577163e-046, +33, 25.880440697073936, 2.585041776791976e-046, +33, 25.880440704524517, 2.5850416224891656e-046, +33, 26.464606821537018, 1.294202982713015e-046, +33, 26.464606828987598, 1.2942028212485916e-046, +33, 27.040671370923519, 6.7991411240400703e-047, +33, 27.0406713783741, 6.7991425220113025e-047, +33, 27.608494073152542, 3.7390875624622383e-047, +33, 27.608494080603123, 3.7390890064190258e-047, +33, 28.167941257357597, 2.1434291178003268e-047, +33, 28.167941264808178, 2.1434297287968616e-047, +33, 28.718893639743328, 1.2763496554107086e-047, +33, 28.718893647193909, 1.276349581640255e-047, +33, 29.261256985366344, 7.8765374703932726e-048, +33, 29.261256992816925, 7.8765383060880799e-048, +33, 29.794976234436035, 5.0202153746787421e-048, +33, 29.794976241886616, 5.0202165028924652e-048, +33, 30.320053435862064, 3.2803380052293672e-048, +33, 30.320053443312645, 3.2803376399507223e-048, +33, 30.836568854749203, 2.186926240398172e-048, +33, 30.836568862199783, 2.1869261872266441e-048, +33, 31.34470284730196, 1.4800222204585884e-048, +33, 31.344702854752541, 1.4800222979922586e-048, +33, 31.844753533601761, 1.0115642031264472e-048, +33, 31.844753541052341, 1.0115637741760139e-048, +33, 32.337142929434776, 7.0902267468841998e-049, +33, 32.337142936885357, 7.0902246585797814e-049, +33, 32.822405032813549, 5.0119448719507044e-049, +33, 32.82240504026413, 5.0119465060716533e-049, +33, 33.301155410706997, 3.528710823086788e-049, +33, 33.301155418157578, 3.5287089306302669e-049, +33, 33.774044148623943, 2.4656993779862083e-049, +33, 33.774044156074524, 2.4656989685917994e-049, +34, 0.79373380541801453, 1.7870320447571981e-008, +34, 0.79373381286859512, 1.7870276506455547e-008, +34, 1.6555418819189072, 2.1693956252335518e-011, +34, 1.6555418893694878, 2.169393482031388e-011, +34, 2.5039884224534035, 5.8343794749490693e-014, +34, 2.5039884299039841, 5.8343740733510059e-014, +34, 3.3406651616096497, 2.7843628540545165e-016, +34, 3.3406651690602303, 2.7843608026959051e-016, +34, 4.1666847914457321, 2.0853448751062561e-018, +34, 4.1666847988963127, 2.0853434333931684e-018, +34, 4.9828581064939499, 2.2651177977520453e-020, +34, 4.9828581139445305, 2.2651171559715021e-020, +34, 5.7898016795516014, 3.3767540686259957e-022, +34, 5.789801687002182, 3.3767524749671601e-022, +34, 6.5879999399185181, 6.6322446953759727e-024, +34, 6.5879999473690987, 6.6322430150818036e-024, +34, 7.3778426647186279, 1.6630098401402096e-025, +34, 7.3778426721692085, 1.6630090886507645e-025, +34, 8.1596490517258644, 5.1918949421969129e-027, +34, 8.159649059176445, 5.1918938102481311e-027, +34, 8.9336837232112885, 1.9774101387184887e-028, +34, 8.933683730661869, 1.9774100074245055e-028, +34, 9.7001679241657257, 9.0334282304926846e-030, +34, 9.7001679316163063, 9.0334252197952801e-030, +34, 10.45928755402565, 4.8796281980007448e-031, +34, 10.459287561476231, 4.8796275501777707e-031, +34, 11.211199007928371, 3.0788693773199207e-032, +34, 11.211199015378952, 3.0788688420038392e-032, +34, 11.956033661961555, 2.2452940986090922e-033, +34, 11.956033669412136, 2.2452936227253024e-033, +34, 12.693901240825653, 1.8750759204376034e-034, +34, 12.693901248276234, 1.8750752842804171e-034, +34, 13.424892462790012, 1.7786452616498199e-035, +34, 13.424892470240593, 1.7786446652143788e-035, +34, 14.149081096053123, 1.9025691211750822e-036, +34, 14.149081103503704, 1.9025689251028157e-036, +34, 14.866525582969189, 2.2801269981849123e-037, +34, 14.866525590419769, 2.2801266851530347e-037, +34, 15.577270358800888, 3.0437692249582344e-038, +34, 15.577270366251469, 3.0437684609885821e-038, +34, 16.281346872448921, 4.5019816965721435e-039, +34, 16.281346879899502, 4.5019810695604887e-039, +34, 16.978774391114712, 7.3425208917329903e-040, +34, 16.978774398565292, 7.3425186631243907e-040, +34, 17.669560678303242, 1.3146865852739081e-040, +34, 17.669560685753822, 1.3146863252096356e-040, +34, 18.35370247066021, 2.573793005179037e-041, +34, 18.35370247811079, 2.5737926524360587e-041, +34, 19.031185887753963, 5.4887057171033031e-042, +34, 19.031185895204544, 5.488704513022213e-042, +34, 19.701986730098724, 1.2705620774407438e-042, +34, 19.701986737549305, 1.2705617046116079e-042, +34, 20.366070702672005, 3.1822514918640349e-043, +34, 20.366070710122585, 3.1822520959707345e-043, +34, 21.023393549025059, 8.5971363864955409e-044, +34, 21.023393556475639, 8.5971368255369006e-044, +34, 21.673901222646236, 2.498003731865251e-044, +34, 21.673901230096817, 2.4980037715197431e-044, +34, 22.317529946565628, 7.7848759226391922e-045, +34, 22.317529954016209, 7.7848753371433522e-045, +34, 22.954206325113773, 2.5952409109277662e-045, +34, 22.954206332564354, 2.5952404568207584e-045, +34, 23.583847463130951, 9.2311729606610371e-046, +34, 23.583847470581532, 9.2311703994594061e-046, +34, 24.206361152231693, 3.4946377430994947e-046, +34, 24.206361159682274, 3.4946373106458168e-046, +34, 24.821646146476269, 1.404567831635744e-046, +34, 24.821646153926849, 1.4045672999262031e-046, +34, 25.429592646658421, 5.9787752597865641e-047, +34, 25.429592654109001, 5.978774144262924e-047, +34, 26.030082978308201, 2.6886705972105962e-047, +34, 26.030082985758781, 2.6886710855104201e-047, +34, 26.622992672026157, 1.2744191540785126e-047, +34, 26.622992679476738, 1.2744190635266817e-047, +34, 27.208192080259323, 6.3488544121732746e-048, +34, 27.208192087709904, 6.3488565442893872e-048, +34, 27.785548649728298, 3.3151982200499414e-048, +34, 27.785548657178879, 3.3151988733358574e-048, +34, 28.354930281639099, 1.8107632911932828e-048, +34, 28.35493028908968, 1.810762622330984e-048, +34, 28.916210018098354, 1.030369686149161e-048, +34, 28.916210025548935, 1.0303698430412018e-048, +34, 29.469272509217262, 6.0883468905536887e-049, +34, 29.469272516667843, 6.0883480072652297e-049, +34, 30.014022909104824, 3.7247230632777596e-049, +34, 30.014022916555405, 3.7247243481664488e-049, +34, 30.5503985658288, 2.3565034476155617e-049, +34, 30.550398573279381, 2.3565045469963732e-049, +34, 31.078383937478065, 1.5295192725419689e-049, +34, 31.078383944928646, 1.5295187474814393e-049, +34, 31.598028488457203, 1.0139825532853324e-049, +34, 31.598028495907784, 1.0139828355540632e-049, +34, 32.109466001391411, 6.8337062479563186e-050, +34, 32.109466008841991, 6.8337052044204809e-050, +34, 32.612932130694389, 4.6594878059160857e-050, +34, 32.61293213814497, 4.6594858546745958e-050, +34, 33.108774498105049, 3.2254931820997371e-050, +34, 33.10877450555563, 3.2254943146700602e-050, +34, 33.597449377179146, 2.2823015656071796e-050, +34, 33.597449384629726, 2.2823005358520434e-050, +34, 34.079502046108246, 1.6115058560593531e-050, +34, 34.079502053558826, 1.6115055152975725e-050, +34, 34.555533915758133, 1.1315645762275127e-050, +34, 34.555533923208714, 1.1315650253690704e-050, +35, 0.79502273350954056, 1.5696564658820398e-008, +35, 0.79502274096012115, 1.569652771494294e-008, +35, 1.6579066589474678, 1.7951755140845492e-011, +35, 1.6579066663980484, 1.795172599177779e-011, +35, 2.507624514400959, 4.5488206656301077e-014, +35, 2.5076245218515396, 4.5488171430200434e-014, +35, 3.3457516953349113, 2.0453895657036801e-016, +35, 3.3457517027854919, 2.0453878756521357e-016, +35, 4.1733897626399994, 1.4433530097271576e-018, +35, 4.17338977009058, 1.4433524229991216e-018, +35, 4.991341657936573, 1.4771508022017578e-020, +35, 4.9913416653871536, 1.4771500867280908e-020, +35, 5.8002184182405472, 2.0747399443706034e-022, +35, 5.8002184256911278, 2.0747394467376026e-022, +35, 6.6005005240440369, 3.8392364113459108e-024, +35, 6.6005005314946175, 3.8392354381122762e-024, +35, 7.3925751224160194, 9.0695765619146772e-026, +35, 7.3925751298666, 9.069572293654555e-026, +35, 8.1767597943544388, 2.6675509270034494e-027, +35, 8.1767598018050194, 2.6675506136249358e-027, +35, 8.9533184096217155, 9.5711573941640687e-029, +35, 8.9533184170722961, 9.5711567380562427e-029, +35, 9.7224722355604172, 4.1189536616823487e-030, +35, 9.7224722430109978, 4.1189526875111826e-030, +35, 10.484407857060432, 2.0959152421505451e-031, +35, 10.484407864511013, 2.0959146742138462e-031, +35, 11.239283010363579, 1.2457104495496718e-032, +35, 11.239283017814159, 1.245710395515959e-032, +35, 11.987230971455574, 8.5570757828342368e-034, +35, 11.987230978906155, 8.5570743326376781e-034, +35, 12.728363960981369, 6.731095753214648e-035, +35, 12.72836396843195, 6.731094549427605e-035, +35, 13.462775729596615, 6.013970900796823e-036, +35, 13.462775737047195, 6.0139693771309301e-036, +35, 14.190543636679649, 6.0591243108769631e-037, +35, 14.19054364413023, 6.0591231024049275e-037, +35, 14.911730267107487, 6.839443929807019e-038, +35, 14.911730274558067, 6.8394415403820541e-038, +35, 15.626384757459164, 8.5993135893576983e-039, +35, 15.626384764909744, 8.5993113703963994e-039, +35, 16.334543816745281, 1.1979757172554445e-039, +35, 16.334543824195862, 1.1979757632006563e-039, +35, 17.036232560873032, 1.8402986282934665e-040, +35, 17.036232568323612, 1.840298447545906e-040, +35, 17.731465205550194, 3.1036764541195221e-041, +35, 17.731465213000774, 3.1036753988139571e-041, +35, 18.420245580375195, 5.7234487752041445e-042, +35, 18.420245587825775, 5.7234471494298037e-042, +35, 19.102567538619041, 1.149770724442714e-042, +35, 19.102567546069622, 1.1497708502322311e-042, +35, 19.778415270149708, 2.507447858257058e-043, +35, 19.778415277600288, 2.507447274767876e-043, +35, 20.447763599455357, 5.9171812907016089e-044, +35, 20.447763606905937, 5.9171816490569785e-044, +35, 21.110578097403049, 1.5064097471606263e-044, +35, 21.11057810485363, 1.5064094343379064e-044, +35, 21.766815282404423, 4.1254753413104886e-045, +35, 21.766815289855003, 4.1254740159034148e-045, +35, 22.416422687470913, 1.2120731601684306e-045, +35, 22.416422694921494, 1.2120728149051467e-045, +35, 23.059338957071304, 3.8105029138120807e-046, +35, 23.059338964521885, 3.8105021101908041e-046, +35, 23.695493943989277, 1.278651848624312e-046, +35, 23.695493951439857, 1.2786521162296595e-046, +35, 24.324808806180954, 4.5686807873754579e-047, +35, 24.324808813631535, 4.5686813030043594e-047, +35, 24.947196207940578, 1.7340976532386943e-047, +35, 24.947196215391159, 1.7340973755762597e-047, +35, 25.562560573220253, 6.9757455173091851e-048, +35, 25.562560580670834, 6.9757442629046094e-048, +35, 26.170798495411873, 2.9671302137983893e-048, +35, 26.170798502862453, 2.9671302835781711e-048, +35, 26.771799370646477, 1.3313735478811511e-048, +35, 26.771799378097057, 1.3313732423828031e-048, +35, 27.365446366369724, 6.2883216285973802e-049, +35, 27.365446373820305, 6.2883196145848755e-049, +35, 27.951617792248726, 3.1179757440882583e-049, +35, 27.951617799699306, 3.1179754652665415e-049, +35, 28.530189104378223, 1.6188565517709766e-049, +35, 28.530189111828804, 1.6188569145137587e-049, +35, 29.101035751402378, 8.7839901000343891e-050, +35, 29.101035758852959, 8.7839933208888784e-050, +35, 29.664037145674229, 4.9628865328970608e-050, +35, 29.664037153124809, 4.9628851842787253e-050, +35, 30.219082154333591, 2.910666302031331e-050, +35, 30.219082161784172, 2.9106651919731774e-050, +35, 30.766076467931271, 1.7662748357670119e-050, +35, 30.766076475381851, 1.7662748729607436e-050, +35, 31.304952368140221, 1.1088754025811909e-050, +35, 31.304952375590801, 1.1088750925555595e-050, +35, 31.835681214928627, 7.148526917550325e-051, +35, 31.835681222379208, 7.1485250674653274e-051, +35, 32.358288533985615, 4.7111519826619542e-051, +35, 32.358288541436195, 4.7111536596976385e-051, +35, 32.872870914638042, 3.1602889534590541e-051, +35, 32.872870922088623, 3.1602885134279907e-051, +35, 33.379612505435944, 2.148091569354062e-051, +35, 33.379612512886524, 2.1480920659934694e-051, +35, 33.878796987235546, 1.4727237873765687e-051, +35, 33.878796994686127, 1.4727234796573971e-051, +35, 34.370810106396675, 1.0388313927106246e-051, +35, 34.370810113847256, 1.0388309311598943e-051, +35, 34.856128677725792, 7.3481861602270532e-052, +35, 34.856128685176373, 7.3481880076428873e-052, +35, 35.335296384990215, 5.1792611113515678e-052, +35, 35.335296392440796, 5.1792623965812728e-052, +35, 35.808892630040646, 3.6254223058064593e-052, +35, 35.808892637491226, 3.6254226968771535e-052, +36, 0.79626041650772095, 1.3835929450802035e-08, +36, 0.79626042395830154, 1.3835896181998894e-08, +36, 1.6601753905415535, 1.4931244784143379e-11, +36, 1.6601753979921341, 1.493122352780069e-11, +36, 2.5111106708645821, 3.5703899506473421e-14, +36, 2.5111106783151627, 3.5703866047036898e-14, +36, 3.3506259918212891, 1.5150630070913857e-16, +36, 3.3506259992718697, 1.5150618212430521e-16, +36, 4.1798121482133865, 1.0089426735600951e-18, +36, 4.1798121556639671, 1.0089419359975001e-18, +36, 4.9994645193219185, 9.7443777441926607e-21, +36, 4.9994645267724991, 9.7443743955897572e-21, +36, 5.8101886734366417, 1.2915850916227745e-22, +36, 5.8101886808872223, 1.2915844512005848e-22, +36, 6.6124612390995026, 2.2554128885556015e-24, +36, 6.6124612465500832, 2.2554125155276728e-24, +36, 7.4066666588187218, 5.0278360283194926e-26, +36, 7.4066666662693024, 5.0278338546774676e-26, +36, 8.1931207999587059, 1.3954345955970732e-27, +36, 8.1931208074092865, 1.3954341072244855e-27, +36, 8.972086638212204, 4.724464485871543e-29, +36, 8.9720866456627846, 4.7244634031993712e-29, +36, 9.7437852323055267, 1.9184692326394543e-30, +36, 9.7437852397561073, 1.9184685785039855e-30, +36, 10.508403599262238, 9.2110610577508696e-32, +36, 10.508403606712818, 9.2110601266004317e-32, +36, 11.266100466251373, 5.1654694352379121e-33, +36, 11.266100473701954, 5.1654692852681363e-33, +36, 12.017010666429996, 3.3478329826958101e-34, +36, 12.017010673880577, 3.3478329207700918e-34, +36, 12.761248469352722, 2.4846199342754033e-35, +36, 12.761248476803303, 2.4846197946102983e-35, +36, 13.498910188674927, 2.0944139010211171e-36, +36, 13.498910196125507, 2.0944138836963017e-36, +36, 14.230076223611832, 1.9908156870458648e-37, +36, 14.230076231062412, 1.9908153770563911e-37, +36, 14.954812712967396, 2.1201017545655606e-38, +36, 14.954812720417976, 2.1201018528061542e-38, +36, 15.673172801733017, 2.5148501205885068e-39, +36, 15.673172809183598, 2.5148494485055796e-39, +36, 16.385197751224041, 3.3052861787263118e-40, +36, 16.385197758674622, 3.3052861741406174e-40, +36, 17.090917713940144, 4.7903393120159658e-41, +36, 17.090917721390724, 4.790337928020491e-41, +36, 17.790352486073971, 7.6221913499235464e-42, +36, 17.790352493524551, 7.6221887512160983e-42, +36, 18.483512006700039, 1.3261747318690734e-42, +36, 18.48351201415062, 1.3261743247879955e-42, +36, 19.170396812260151, 2.5137057203282608e-43, +36, 19.170396819710732, 2.5137052677277973e-43, +36, 19.850998379290104, 5.1727759046768898e-44, +36, 19.850998386740685, 5.1727766444918836e-44, +36, 20.525299377739429, 1.1519505703963367e-44, +36, 20.52529938519001, 1.1519504260767373e-44, +36, 21.193273916840553, 2.7678273069030527e-45, +36, 21.193273924291134, 2.767827798374501e-45, +36, 21.854887641966343, 7.1550244945029494e-46, +36, 21.854887649416924, 7.1550255906707147e-46, +36, 22.510097898542881, 1.984671431191121e-46, +36, 22.510097905993462, 1.9846717706719504e-46, +36, 23.158853799104691, 5.8920553246780296e-47, +36, 23.158853806555271, 5.8920563816719921e-47, +36, 23.801096305251122, 1.8676209958225792e-47, +36, 23.801096312701702, 1.8676207067911573e-47, +36, 24.436758331954479, 6.3057370674808548e-48, +36, 24.43675833940506, 6.305738069895672e-48, +36, 25.06576481461525, 2.2626653116936076e-48, +36, 25.06576482206583, 2.2626651438466747e-48, +36, 25.688032925128937, 8.609447490993131e-49, +36, 25.688032932579517, 8.6094493022667365e-49, +36, 26.303472265601158, 3.4661501360200687e-49, +36, 26.303472273051739, 3.4661492034038488e-49, +36, 26.9119853079319, 1.4732834984629157e-49, +36, 26.911985315382481, 1.4732837705852057e-49, +36, 27.513467893004417, 6.5968583742268946e-50, +36, 27.513467900454998, 6.5968571516253582e-50, +36, 28.107810139656067, 3.1053437896353887e-50, +36, 28.107810147106647, 3.1053426179920777e-50, +36, 28.694897629320621, 1.5328565224865415e-50, +36, 28.694897636771202, 1.5328568405292139e-50, +36, 29.274613127112389, 7.9154003962363097e-51, +36, 29.274613134562969, 7.9153981703693011e-51, +36, 29.846839085221291, 4.2678541181450703e-51, +36, 29.846839092671871, 4.2678539866995966e-51, +36, 30.411460973322392, 2.3948652243180979e-51, +36, 30.411460980772972, 2.394865944405174e-51, +36, 30.96837193518877, 1.3944290618424927e-51, +36, 30.968371942639351, 1.3944293152714109e-51, +36, 31.5174790173769, 8.3994203358922169e-52, +36, 31.51747902482748, 8.3994196694359044e-52, +36, 32.058711349964142, 5.2303978505284272e-52, +36, 32.058711357414722, 5.2303986168397962e-52, +36, 32.592030584812164, 3.3488642311760486e-52, +36, 32.592030592262745, 3.3488629175690189e-52, +36, 33.117443718016148, 2.1935874637218713e-52, +36, 33.117443725466728, 2.1935864157428464e-52, +36, 33.635017700493336, 1.4640573341386401e-52, +36, 33.635017707943916, 1.4640577637638097e-52, +36, 34.144894443452358, 9.9145231314678597e-53, +36, 34.144894450902939, 9.9145189377303778e-53, +36, 34.647303439676762, 6.7831948011401348e-53, +36, 34.647303447127342, 6.7831938694253262e-53, +36, 35.142567783594131, 4.728695673093241e-53, +36, 35.142567791044712, 4.728693640419844e-53, +36, 35.631099842488766, 3.3479489237088613e-53, +36, 35.631099849939346, 3.3479487366331723e-53, +36, 36.1133848503232, 2.3658904809482673e-53, +36, 36.113384857773781, 2.3658904632138702e-53, +36, 36.589955143630505, 1.6633995727057523e-53, +36, 36.589955151081085, 1.6634000834145591e-53, +37, 0.79745029658079147, 1.2236661930214837e-08, +37, 0.79745030403137207, 1.2236628758929966e-08, +37, 1.6623546034097672, 1.2479305303495537e-11, +37, 1.6623546108603477, 1.2479287682904157e-11, +37, 2.5144571959972382, 2.8202775702029049e-14, +37, 2.5144572034478188, 2.8202750550262852e-14, +37, 3.3553027361631393, 1.1310984736219153e-16, +37, 3.3553027436137199, 1.1310978210383242e-16, +37, 4.1859716475009918, 7.1192220955675187e-19, +37, 4.1859716549515724, 7.1192189237113434e-19, +37, 5.0072519481182098, 6.4985394002265385e-21, +37, 5.0072519555687904, 6.4985349578088278e-21, +37, 5.8197439312934875, 8.1409638138242418e-23, +37, 5.8197439387440681, 8.1409615658792421e-23, +37, 6.623920351266861, 1.3435858973256726e-24, +37, 6.6239203587174416, 1.3435851897008275e-24, +37, 7.4201629906892776, 2.8307382521732816e-26, +37, 7.4201629981398582, 2.8307372642654064e-26, +37, 8.2087858989834785, 7.4250550358011096e-28, +37, 8.2087859064340591, 7.425054233214666e-28, +37, 8.9900510162115097, 2.3757781581308228e-29, +37, 8.9900510236620903, 2.3757776969798374e-29, +37, 9.7641790360212326, 9.117207529070504e-31, +37, 9.7641790434718132, 9.1172056695682319e-31, +37, 10.531357169151306, 4.1367659138735107e-32, +37, 10.531357176601887, 4.1367656716179671e-32, +37, 11.291744880378246, 2.1922792746035818e-33, +37, 11.291744887828827, 2.1922790321494946e-33, +37, 12.045478232204914, 1.3426890905806162e-34, +37, 12.045478239655495, 1.3426888392460162e-34, +37, 12.792673192918301, 9.4164802467780859e-36, +37, 12.792673200368881, 9.4164787873069284e-36, +37, 13.533428221940994, 7.5006766342224927e-37, +37, 13.533428229391575, 7.5006765352776218e-37, +37, 14.267826303839684, 6.7370840809894097e-38, +37, 14.267826311290264, 6.7370818558224836e-38, +37, 14.995936617255211, 6.7794683533193956e-39, +37, 14.995936624705791, 6.7794685669393241e-39, +37, 15.717815771698952, 7.5988197334410899e-40, +37, 15.717815779149532, 7.5988200044185489e-40, +37, 16.433508925139904, 9.4370881848402715e-41, +37, 16.433508932590485, 9.4370869322809968e-41, +37, 17.143050618469715, 1.2923864433326415e-41, +37, 17.143050625920296, 1.2923862031149783e-41, +37, 17.846465460956097, 1.9431631602162195e-42, +37, 17.846465468406677, 1.9431627337446246e-42, +37, 18.543768703937531, 3.1948008999823789e-43, +37, 18.543768711388111, 3.1948010113204146e-43, +37, 19.234966672956944, 5.7225142187488541e-44, +37, 19.234966680407524, 5.7225139397996951e-44, +37, 19.920057162642479, 1.1128777706945255e-44, +37, 19.92005717009306, 1.1128779257270233e-44, +37, 20.599029682576656, 2.3422790968973117e-45, +37, 20.599029690027237, 2.3422787459449697e-45, +37, 21.271865725517273, 5.3194139126989398e-46, +37, 21.271865732967854, 5.3194138487209108e-46, +37, 21.938538894057274, 1.299888245542366e-46, +37, 21.938538901507854, 1.2998883349852924e-46, +37, 22.599015057086945, 3.4089243411358843e-47, +37, 22.599015064537525, 3.408924229182079e-47, +37, 23.253252446651459, 9.5699439516338502e-48, +37, 23.253252454102039, 9.5699415030365759e-48, +37, 23.901201739907265, 2.8690919156987703e-48, +37, 23.901201747357845, 2.8690914333854321e-48, +37, 24.54280611872673, 9.1649001925442593e-49, +37, 24.542806126177311, 9.1649005780835866e-49, +37, 25.17800135165453, 3.1124278518690985e-49, +37, 25.17800135910511, 3.1124268541854008e-49, +37, 25.806715928018093, 1.1213100444461474e-49, +37, 25.806715935468674, 1.1213100629654459e-49, +37, 26.428871154785156, 4.2765508470155986e-50, +37, 26.428871162235737, 4.2765493833034662e-50, +37, 27.044381447136402, 1.7230608895836024e-50, +37, 27.044381454586983, 1.723060324124993e-50, +37, 27.653154633939266, 7.3189360531595413e-51, +37, 27.653154641389847, 7.3189369856880685e-51, +37, 28.255092471837997, 3.270635849960595e-51, +37, 28.255092479288578, 3.2706356611225313e-51, +37, 28.850091427564621, 1.5346672258666679e-51, +37, 28.850091435015202, 1.5346672310873133e-51, +37, 29.438043721020222, 7.543141992030555e-52, +37, 29.438043728470802, 7.543143707916083e-52, +37, 30.018838845193386, 3.874949153397152e-52, +37, 30.018838852643967, 3.874947763251735e-52, +37, 30.592365711927414, 2.0766876525058779e-52, +37, 30.592365719377995, 2.0766871501237398e-52, +37, 31.158515512943268, 1.1576724655066195e-52, +37, 31.158515520393848, 1.1576721953298155e-52, +37, 31.717185698449612, 6.6936395490480338e-53, +37, 31.717185705900192, 6.6936420210855687e-53, +37, 32.26828520745039, 4.0030047819768722e-53, +37, 32.26828521490097, 4.0030029042549631e-53, +37, 32.811741434037685, 2.4728033585097465e-53, +37, 32.811741441488266, 2.472804014857275e-53, +37, 33.347508952021599, 1.5724714477623819e-53, +37, 33.347508959472179, 1.572471299321689e-53, +37, 33.875580437481403, 1.0235954646285162e-53, +37, 33.875580444931984, 1.0235955617103327e-53, +37, 34.395999230444431, 6.7952496882961977e-54, +37, 34.395999237895012, 6.7952461226991219e-54, +37, 34.908872827887535, 4.5825066833067962e-54, +37, 34.908872835338116, 4.5825058071678801e-54, +37, 35.414385139942169, 3.126558694401219e-54, +37, 35.41438514739275, 3.1265575278948968e-54, +37, 35.91280460357666, 2.1535066491957579e-54, +37, 35.912804611027241, 2.153507153607943e-54, +37, 36.404484450817108, 1.5247311886236291e-54, +37, 36.404484458267689, 1.5247312487526864e-54, +37, 36.889852896332741, 1.079237350892692e-54, +37, 36.889852903783321, 1.0792377265221853e-54, +37, 37.369393646717072, 7.6138428826956967e-55, +37, 37.369393654167652, 7.6138390265469377e-55, +37, 37.843620575964451, 5.3377879130874528e-55, +37, 37.843620583415031, 5.3377878086121768e-55, +38, 0.79859550297260284, 1.0856580287562025e-08, +38, 0.79859551042318344, 1.0856554375618626e-08, +38, 1.6644502282142639, 1.0478085209213337e-11, +38, 1.6644502356648445, 1.0478073726155761e-11, +38, 2.5176734104752541, 2.2412324303407208e-14, +38, 2.5176734179258347, 2.2412296392981232e-14, +38, 3.3597952127456665, 8.5076785133405888e-17, +38, 3.3597952201962471, 8.5076706729828499e-17, +38, 4.1918860524892807, 5.0683042781997589e-19, +38, 4.1918860599398613, 5.0683022594556336e-19, +38, 5.0147268176078796, 4.378910643033748e-21, +38, 5.0147268250584602, 4.3789086546405285e-21, +38, 5.828912615776062, 5.1921247627005068e-23, +38, 5.8289126232266426, 5.1921222391432412e-23, +38, 6.6349124535918236, 8.1105425045874404e-25, +38, 6.6349124610424042, 8.110539774075029e-25, +38, 7.4331053867936134, 1.617316665311046e-26, +38, 7.433105394244194, 1.617316440770334e-26, +38, 8.2238036170601845, 4.0151378429904181e-28, +38, 8.2238036245107651, 4.015136984178548e-28, +38, 9.0072679594159126, 1.2159212965962104e-29, +38, 9.0072679668664932, 1.2159208207433248e-29, +38, 9.7837185859680176, 4.4162423160286735e-31, +38, 9.7837185934185982, 4.4162416946544442e-31, +38, 10.553342707455158, 1.8964272424010951e-32, +38, 10.553342714905739, 1.8964267905280257e-32, +38, 11.316300310194492, 9.5114672897534994e-34, +38, 11.316300317645073, 9.5114641548621261e-34, +38, 12.072728417813778, 5.5130997617066586e-35, +38, 12.072728425264359, 5.5130983436961545e-35, +38, 12.822744384407997, 3.6590686844435314e-36, +38, 12.822744391858578, 3.6590683149523385e-36, +38, 13.566448464989662, 2.758274929688359e-37, +38, 13.566448472440243, 2.7582745019573862e-37, +38, 14.303925864398479, 2.3445435874808282e-38, +38, 14.30392587184906, 2.3445436870215827e-38, +38, 15.035248324275017, 2.2326837025369582e-39, +38, 15.035248331725597, 2.2326833393720502e-39, +38, 15.760475471615791, 2.3682080599328576e-40, +38, 15.760475479066372, 2.3682075080605805e-40, +38, 16.479655846953392, 2.7832534710135998e-41, +38, 16.479655854403973, 2.7832532879192518e-41, +38, 17.192827761173248, 3.6070297549176349e-42, +38, 17.192827768623829, 3.6070286895740662e-42, +38, 17.900020033121109, 5.1323150247195217e-43, +38, 17.90002004057169, 5.1323140369858444e-43, +38, 18.601252518594265, 7.9855046226895403e-44, +38, 18.601252526044846, 7.9855030321548096e-44, +38, 19.296536602079868, 1.3536668948114345e-44, +38, 19.296536609530449, 1.3536664254310531e-44, +38, 19.985875576734543, 2.4914698664149824e-45, +38, 19.985875584185123, 2.4914700473896849e-45, +38, 20.669264905154705, 4.9631023266169206e-46, +38, 20.669264912605286, 4.9631015730240982e-46, +38, 21.346692517399788, 1.0668796068050406e-46, +38, 21.346692524850368, 1.0668792858037233e-46, +38, 22.018138960003853, 2.4679368474617229e-47, +38, 22.018138967454433, 2.46793637331118e-47, +38, 22.683577544987202, 6.1273384648171703e-48, +38, 22.683577552437782, 6.1273388538819925e-48, +38, 23.342974461615086, 1.6287464319431956e-48, +38, 23.342974469065666, 1.6287465589289163e-48, +38, 23.996288873255253, 4.6244141135970417e-49, +38, 23.996288880705833, 4.6244139707011605e-49, +38, 24.643472984433174, 1.3992813641664737e-49, +38, 24.643472991883755, 1.3992815290961278e-49, +38, 25.284472092986107, 4.5025702693911814e-50, +38, 25.284472100436687, 4.5025703981392466e-50, +38, 25.919224686920643, 1.5375035399490303e-50, +38, 25.919224694371223, 1.5375036072619918e-50, +38, 26.547662526369095, 5.5601877247885129e-51, +38, 26.547662533819675, 5.5601876296393229e-51, +38, 27.169710800051689, 2.1252757522561053e-51, +38, 27.16971080750227, 2.1252762417162567e-51, +38, 27.785288318991661, 8.5691767255137375e-52, +38, 27.785288326442242, 8.5691769176802675e-52, +38, 28.394307859241962, 3.6375520068298642e-52, +38, 28.394307866692543, 3.6375509456924231e-52, +38, 28.996676616370678, 1.6224427641883163e-52, +38, 28.996676623821259, 1.622442697148659e-52, +38, 29.592296853661537, 7.5897562486105309e-53, +38, 29.592296861112118, 7.5897537052591606e-53, +38, 30.181066893041134, 3.7153358213302024e-53, +38, 30.181066900491714, 3.7153352370458552e-53, +38, 30.762882404029369, 1.8991275765178409e-53, +38, 30.76288241147995, 1.8991268090216899e-53, +38, 31.337638281285763, 1.011897730905427e-53, +38, 31.337638288736343, 1.011898019843859e-53, +38, 31.905231095850468, 5.6053554722310255e-54, +38, 31.905231103301048, 5.6053535423071908e-54, +38, 32.465562544763088, 3.2191655316314136e-54, +38, 32.465562552213669, 3.2191654248135054e-54, +38, 33.018543861806393, 1.911716584704686e-54, +38, 33.018543869256973, 1.9117164960140519e-54, +38, 33.564101710915565, 1.1716842069253844e-54, +38, 33.564101718366146, 1.171683748939402e-54, +38, 34.102185644209385, 7.400328173238866e-55, +38, 34.102185651659966, 7.4003274298963434e-55, +38, 34.63277729600668, 4.7868574640208661e-55, +38, 34.63277730345726, 4.7868570950777136e-55, +38, 35.15590126812458, 3.1601245063659552e-55, +38, 35.155901275575161, 3.1601256141113849e-55, +38, 35.671637006103992, 2.1213819000229862e-55, +38, 35.671637013554573, 2.1213818245865819e-55, +38, 36.180130407214165, 1.4425889599279148e-55, +38, 36.180130414664745, 1.4425882771152319e-55, +38, 36.681602776050568, 9.8990384739542851e-56, +38, 36.681602783501148, 9.8990409760224132e-56, +38, 37.176354207098484, 6.9441499664883014e-56, +38, 37.176354214549065, 6.9441458354194441e-56, +38, 37.664758898317814, 4.9192031215738617e-56, +38, 37.664758905768394, 4.9192014222924419e-56, +38, 38.147251442074776, 3.4788201160648105e-56, +38, 38.147251449525356, 3.4788200837872443e-56, +38, 38.624306313693523, 2.4486355090333834e-56, +38, 38.624306321144104, 2.4486357196694196e-56, +39, 0.79969886690378189, 9.6612143778886286e-09, +39, 0.79969887435436249, 9.6611833659543116e-09, +39, 1.6664676442742348, 8.8363260213997706e-12, +39, 1.6664676517248154, 8.8363150690020779e-12, +39, 2.5207678005099297, 1.7913041342876869e-14, +39, 2.5207678079605103, 1.7913024593913769e-14, +39, 3.3641155064105988, 6.4446628031215182e-17, +39, 3.3641155138611794, 6.4446578879089881e-17, +39, 4.1975715160369873, 3.6388503086830051e-19, +39, 4.1975715234875679, 3.6388472458720568e-19, +39, 5.0219098404049873, 2.9797587595903091e-21, +39, 5.0219098478555679, 2.9797574573664833e-21, +39, 5.8377205207943916, 3.3486821124159864e-23, +39, 5.8377205282449722, 3.3486810759664543e-23, +39, 6.6454688534140587, 4.9578250919485837e-25, +39, 6.6454688608646393, 4.9578240233007194e-25, +39, 7.4455311968922615, 9.3701457525565861e-27, +39, 7.4455312043428421, 9.3701426658016626e-27, +39, 8.2382178753614426, 2.2047425437621379e-28, +39, 8.2382178828120232, 2.2047414756897301e-28, +39, 9.0237884894013405, 6.3279677678366445e-30, +39, 9.0237884968519211, 6.3279653079178988e-30, +39, 9.8024625554680824, 2.1782510395644173e-31, +39, 9.802462562918663, 2.1782507909039509e-31, +39, 10.574427150189877, 8.8650607816370113e-33, +39, 10.574427157640457, 8.8650590820738999e-33, +39, 11.339842580258846, 4.21383409134695e-34, +39, 11.339842587709427, 4.2138338754137614e-34, +39, 12.098846592009068, 2.3147510097171507e-35, +39, 12.098846599459648, 2.3147505763690007e-35, +39, 12.851557679474354, 1.4559671379309136e-36, +39, 12.851557686924934, 1.4559669477038534e-36, +39, 13.598077602684498, 1.0401252086311623e-37, +39, 13.598077610135078, 1.0401250446118563e-37, +39, 14.338493429124355, 8.3785468663638118e-39, +39, 14.338493436574936, 8.3785458033752376e-39, +39, 15.072879135608673, 7.5612898818531167e-40, +39, 15.072879143059254, 7.5612886562067478e-40, +39, 15.801296919584274, 7.6005354226141264e-41, +39, 15.801296927034855, 7.6005337498656611e-41, +39, 16.523798257112503, 8.4650896576241533e-42, +39, 16.523798264563084, 8.4650886253305973e-42, +39, 17.240424759685993, 1.0396412702585144e-42, +39, 17.240424767136574, 1.0396412770497945e-42, +39, 17.951208882033825, 1.4018620637042408e-43, +39, 17.951208889484406, 1.4018616305158902e-43, +39, 18.656174533069134, 2.067083503736078e-44, +39, 18.656174540519714, 2.0670834410366982e-44, +39, 19.355337493121624, 3.3207815601122839e-45, +39, 19.355337500572205, 3.3207812480398958e-45, +39, 20.048705853521824, 5.7925577857641326e-46, +39, 20.048705860972404, 5.7925562215888879e-46, +39, 20.73628031462431, 1.0936340009548834e-46, +39, 20.73628032207489, 1.0936338912944408e-46, +39, 21.418054424226284, 2.2282416173411488e-47, +39, 21.418054431676865, 2.2282419515714618e-47, +39, 22.094014786183834, 4.8858532361936634e-48, +39, 22.094014793634415, 4.8858528829628252e-48, +39, 22.764141239225864, 1.1499462002800235e-48, +39, 22.764141246676445, 1.1499460310878093e-48, +39, 23.428406953811646, 2.8980663905193471e-49, +39, 23.428406961262226, 2.898066276934411e-49, +39, 24.086778528988361, 7.8023090836169274e-50, +39, 24.086778536438942, 7.8023071601284799e-50, +39, 24.739216089248657, 2.2390305872090235e-50, +39, 24.739216096699238, 2.2390301640135304e-50, +39, 25.385673321783543, 6.8343680810092181e-51, +39, 25.385673329234123, 6.8343669565535207e-51, +39, 26.026097558438778, 2.2143788932280574e-51, +39, 26.026097565889359, 2.214379341700106e-51, +39, 26.660429820418358, 7.6008658486826571e-52, +39, 26.660429827868938, 7.600864771708126e-52, +39, 27.288604959845543, 2.7586423498874149e-52, +39, 27.288604967296124, 2.758642998550457e-52, +39, 27.910551734268665, 1.0566445834836509e-52, +39, 27.910551741719246, 1.0566448391841193e-52, +39, 28.526193052530289, 4.2633663243585857e-53, +39, 28.526193059980869, 4.2633674856406724e-53, +39, 29.135446235537529, 1.8086671216346443e-53, +39, 29.13544624298811, 1.8086664439032788e-53, +39, 29.738223470747471, 8.0525691421281269e-54, +39, 29.738223478198051, 8.0525661133114887e-54, +39, 30.334432370960712, 3.7560490711121251e-54, +39, 30.334432378411293, 3.7560482528346272e-54, +39, 30.923976838588715, 1.8315301227125887e-54, +39, 30.923976846039295, 1.8315294529778216e-54, +39, 31.506758250296116, 9.3176473955502718e-55, +39, 31.506758257746696, 9.3176498591590885e-55, +39, 32.082677021622658, 4.9370713759437589e-55, +39, 32.082677029073238, 4.9370727760416717e-55, +39, 32.651634819805622, 2.7182652304916268e-55, +39, 32.651634827256203, 2.7182656586123935e-55, +39, 33.213537447154522, 1.5509397574117082e-55, +39, 33.213537454605103, 1.5509397191650001e-55, +39, 33.76829868555069, 9.1478312540410161e-56, +39, 33.76829869300127, 9.1478350368113743e-56, +39, 34.315845258533955, 5.5636458609342363e-56, +39, 34.315845265984535, 5.5636451195134233e-56, +39, 34.856123223900795, 3.4904081103721966e-56, +39, 34.856123231351376, 3.4904077582346387e-56, +39, 35.389105789363384, 2.2434410644709078e-56, +39, 35.389105796813965, 2.2434413425309701e-56, +39, 35.914802670478821, 1.4725708246351153e-56, +39, 35.914802677929401, 1.4725709043207682e-56, +39, 36.433270551264286, 9.8372978663326332e-57, +39, 36.433270558714867, 9.8372937681131233e-57, +39, 36.944623731076717, 6.6643897045912897e-57, +39, 36.944623738527298, 6.6643904738423579e-57, +39, 37.449043244123459, 4.5619506187543033e-57, +39, 37.449043251574039, 4.5619516037469389e-57, +39, 37.946782201528549, 3.1638952883437559e-57, +39, 37.94678220897913, 3.1638958376894018e-57, +39, 38.438164800405502, 2.2414198125250737e-57, +39, 38.438164807856083, 2.241419676994563e-57, +39, 38.92357762157917, 1.5874855857137775e-57, +39, 38.923577629029751, 1.5874850938683276e-57, +39, 39.403453819453716, 1.1208658754145761e-57, +39, 39.403453826904297, 1.1208655216309198e-57, +39, 39.878253020346165, 7.8686506952910403e-58, +39, 39.878253027796745, 7.8686503959234645e-58, +40, 0.80076299607753754, 8.6220839569040916e-09, +40, 0.80076300352811813, 8.6220617969632951e-09, +40, 1.6684117615222931, 7.482856429765271e-12, +40, 1.6684117689728737, 7.4828434084303384e-12, +40, 2.5237480700016022, 1.4395249763313945e-14, +40, 2.5237480774521828, 1.4395234884855117e-14, +40, 3.3682745918631554, 4.914945972398221e-17, +40, 3.368274599313736, 4.9149416138302671e-17, +40, 4.2030427530407906, 2.6336469660088453e-19, +40, 4.2030427604913712, 2.6336449591696725e-19, +40, 5.0288198664784431, 2.04669313220365e-21, +40, 5.0288198739290237, 2.0466922069270797e-21, +40, 5.8461910635232925, 2.182856581073528e-23, +40, 5.8461910709738731, 2.1828557610574724e-23, +40, 6.6556179970502853, 3.0670597274357603e-25, +40, 6.6556180045008659, 3.0670587692154617e-25, +40, 7.4574743509292603, 5.5011817992950591e-27, +40, 7.4574743583798409, 5.5011804116695148e-27, +40, 8.2520685344934464, 1.2284121858449798e-28, +40, 8.2520685419440269, 1.2284119905636949e-28, +40, 9.039658859372139, 3.3459882136107596e-30, +40, 9.0396588668227196, 3.3459876354353264e-30, +40, 9.8204641044139862, 1.093046091664667e-31, +40, 9.8204641118645668, 1.093045912726458e-31, +40, 10.594671085476875, 4.221612631880723e-33, +40, 10.594671092927456, 4.2216116455431198e-33, +40, 11.362440258264542, 1.9043015174724808e-34, +40, 11.362440265715122, 1.9043013466761215e-34, +40, 12.123909913003445, 9.927033740522332e-36, +40, 12.123909920454025, 9.9270318491872625e-36, +40, 12.87919944524765, 5.9254204573291864e-37, +40, 12.879199452698231, 5.9254185761345363e-37, +40, 13.628411874175072, 4.0169933059966589e-38, +40, 13.628411881625652, 4.0169919637532185e-38, +40, 14.371635846793652, 3.0706343996807527e-39, +40, 14.371635854244232, 3.0706334592178465e-39, +40, 15.10894725471735, 2.6296368343236479e-40, +40, 15.108947262167931, 2.629636883937738e-40, +40, 15.840410508215427, 2.5083165315198936e-41, +40, 15.840410515666008, 2.508316135677605e-41, +40, 16.566079638898373, 2.6509819483710857e-42, +40, 16.566079646348953, 2.6509813339366169e-42, +40, 17.285999126732349, 3.0895557761508032e-43, +40, 17.28599913418293, 3.0895547199180405e-43, +40, 18.000204637646675, 3.9532735587946378e-44, +40, 18.000204645097256, 3.9532738604335661e-44, +40, 18.708723567426205, 5.5316336293557132e-45, +40, 18.708723574876785, 5.5316323436324288e-45, +40, 19.411575593054295, 8.4330816952067172e-46, +40, 19.411575600504875, 8.4330793832693508e-46, +40, 20.10877301543951, 1.3959734563971271e-46, +40, 20.108773022890091, 1.3959734325249744e-46, +40, 20.800321087241173, 2.5012329433504756e-47, +40, 20.800321094691753, 2.5012321368344211e-47, +40, 21.486218318343163, 4.8365841541015896e-48, +40, 21.486218325793743, 4.8365827723172397e-48, +40, 22.166456647217274, 1.0065510121004077e-48, +40, 22.166456654667854, 1.0065511177259529e-48, +40, 22.841021612286568, 2.2486596435899771e-49, +40, 22.841021619737148, 2.2486595284896741e-49, +40, 23.509892523288727, 5.3795421688687128e-50, +40, 23.509892530739307, 5.3795422441328151e-50, +40, 24.17304252833128, 1.3749934138013411e-50, +40, 24.17304253578186, 1.3749936145620943e-50, +40, 24.830438703298569, 3.7466207092405214e-51, +40, 24.830438710749149, 3.7466195892844483e-51, +40, 25.482042148709297, 1.0860643386448439e-51, +40, 25.482042156159878, 1.0860642115645083e-51, +40, 26.12780799716711, 3.3425556909891041e-52, +40, 26.127808004617691, 3.3425556313746612e-52, +40, 26.767685502767563, 1.0901108511699288e-52, +40, 26.767685510218143, 1.0901105953917385e-52, +40, 27.401618115603924, 3.7602645981940591e-53, +40, 27.401618123054504, 3.7602652607389148e-53, +40, 28.029543526470661, 1.369396504373224e-53, +40, 28.029543533921242, 1.3693960150232702e-53, +40, 28.651393860578537, 5.2556184134729698e-54, +40, 28.651393868029118, 5.2556168198097212e-54, +40, 29.267095804214478, 2.1219341342039526e-54, +40, 29.267095811665058, 2.121934465865967e-54, +40, 29.876570880413055, 8.9967556766314939e-55, +40, 29.876570887863636, 8.9967531699707271e-55, +40, 30.479735873639584, 3.9986560136554673e-55, +40, 30.479735881090164, 3.9986558489137015e-55, +40, 31.076503314077854, 1.8599753253287926e-55, +40, 31.076503321528435, 1.8599757156271693e-55, +40, 31.66678225249052, 9.0360299626257797e-56, +40, 31.666782259941101, 9.036026700725493e-56, +40, 32.250479318201542, 4.5760898608462063e-56, +40, 32.250479325652122, 4.5760887986740979e-56, +40, 32.827500082552433, 2.4117678880943317e-56, +40, 32.827500090003014, 2.4117684357547485e-56, +40, 33.397750958800316, 1.3201202030406543e-56, +40, 33.397750966250896, 1.3201196555992101e-56, +40, 33.961141757667065, 7.4847204235456685e-57, +40, 33.961141765117645, 7.4847221559011106e-57, +40, 34.517588913440704, 4.3855925974584337e-57, +40, 34.517588920891285, 4.385593435217874e-57, +40, 35.067019812762737, 2.6491586845734461e-57, +40, 35.067019820213318, 2.6491580564154119e-57, +40, 35.609378203749657, 1.6497934498550021e-57, +40, 35.609378211200237, 1.649793368648089e-57, +40, 36.144630901515484, 1.0536773043718698e-57, +40, 36.144630908966064, 1.0536776720991313e-57, +40, 36.672775842249393, 6.8759153785157124e-58, +40, 36.672775849699974, 6.8759166513298611e-58, +40, 37.193851247429848, 4.5699678490685328e-58, +40, 37.193851254880428, 4.5699698575441556e-58, +40, 37.707945220172405, 3.0831903169784489e-58, +40, 37.707945227622986, 3.0831907114952658e-58, +40, 38.215204663574696, 2.1042675579982823e-58, +40, 38.215204671025276, 2.1042678320825935e-58, +40, 38.715841598808765, 1.44772765360699e-58, +40, 38.715841606259346, 1.4477275844728336e-58, +40, 39.210134834051132, 1.0212982981853514e-58, +40, 39.210134841501713, 1.0212978783646425e-58, +40, 39.698425233364105, 7.2384658423559274e-59, +40, 39.698425240814686, 7.2384626057588699e-59, +40, 40.181104280054569, 5.1224147534757263e-59, +40, 40.18110428750515, 5.1224148163640331e-59, +40, 40.658597514033318, 3.6091357864666219e-59, +40, 40.658597521483898, 3.6091362660315758e-59, +41, 0.80179024487733841, 7.715754717994936e-09, +41, 0.80179025232791901, 7.7157302111467959e-09, +41, 1.6702870726585388, 6.3618331174118259e-12, +41, 1.6702870801091194, 6.3618226594372705e-12, +41, 2.5266212671995163, 1.162850848252617e-14, +41, 2.5266212746500969, 1.1628493459927956e-14, +41, 3.3722824975848198, 3.7724846530163349e-17, +41, 3.3722825050354004, 3.7724808311832636e-17, +41, 4.2083131596446037, 1.920778816112959e-19, +41, 4.2083131670951843, 1.9207773576706867e-19, +41, 5.0354740768671036, 1.4183648576268382e-21, +41, 5.0354740843176842, 1.4183641694691616e-21, +41, 5.8543455973267555, 1.4374026410740077e-23, +41, 5.8543456047773361, 1.4374021204448828e-23, +41, 6.6653857976198196, 1.9190885863488743e-25, +41, 6.6653858050704002, 1.919087824425809e-25, +41, 7.4689657092094421, 3.270760808097721e-27, +41, 7.4689657166600227, 3.2707591863959973e-27, +41, 8.2653918191790581, 6.9399488701523391e-29, +41, 8.2653918266296387, 6.9399461386502186e-29, +41, 9.0549211129546165, 1.7961988013370199e-30, +41, 9.0549211204051971, 1.7961986170950286e-30, +41, 9.8377715349197388, 5.5755077823717882e-32, +41, 9.8377715423703194, 5.5755069110678978e-32, +41, 10.614129528403282, 2.0461508033605068e-33, +41, 10.614129535853863, 2.0461500591140822e-33, +41, 11.384155571460724, 8.7701108074102184e-35, +41, 11.384155578911304, 8.7701090331652339e-35, +41, 12.147988334298134, 4.3440568875966986e-36, +41, 12.147988341748714, 4.3440564786178534e-36, +41, 12.905747920274734, 2.4637601753857343e-37, +41, 12.905747927725315, 2.4637596423878285e-37, +41, 13.657538384199142, 1.5870121728469763e-38, +41, 13.657538391649723, 1.5870116574060113e-38, +41, 14.403449714183807, 1.1526673651546713e-39, +41, 14.403449721634388, 1.1526669722593979e-39, +41, 15.14355943351984, 9.3791993648929087e-41, +41, 15.143559440970421, 9.3791977758924899e-41, +41, 15.877933889627457, 8.5004955033105688e-42, +41, 15.877933897078037, 8.5004957216667634e-42, +41, 16.606629312038422, 8.53610276763418e-43, +41, 16.606629319489002, 8.5361021103963203e-43, +41, 17.32969269156456, 9.4523530357048223e-44, +41, 17.329692699015141, 9.4523506752230666e-44, +41, 18.047162488102913, 1.1491939884925788e-44, +41, 18.047162495553493, 1.1491939201245561e-44, +41, 18.759069196879864, 1.5278674206431506e-45, +41, 18.759069204330444, 1.5278669100935831e-45, +41, 19.465435892343521, 2.2131950384106822e-46, +41, 19.465435899794102, 2.2131952234933592e-46, +41, 20.166278555989265, 3.4811292143934784e-47, +41, 20.166278563439846, 3.4811282177669865e-47, +41, 20.861606501042843, 5.9267645821030561e-48, +41, 20.861606508493423, 5.9267646789506383e-48, +41, 21.55142255872488, 1.089026097386482e-48, +41, 21.551422566175461, 1.089026021431083e-48, +41, 22.235723368823528, 2.1537298245085798e-49, +41, 22.235723376274109, 2.1537300799057606e-49, +41, 22.914499513804913, 4.5725708362403891e-50, +41, 22.914499521255493, 4.5725705992050573e-50, +41, 23.587735697627068, 1.0396699443959863e-50, +41, 23.587735705077648, 1.0396697016213483e-50, +41, 24.255410842597485, 2.525830841332298e-51, +41, 24.255410850048065, 2.5258301837673761e-51, +41, 24.917498178780079, 6.5425362831654044e-52, +41, 24.917498186230659, 6.5425348121202585e-52, +41, 25.573965318500996, 1.8031239693612795e-52, +41, 25.573965325951576, 1.8031234753289202e-52, +41, 26.224774323403835, 5.2769875821328614e-53, +41, 26.224774330854416, 5.276987836076435e-53, +41, 26.869881734251976, 1.6368353014029421e-53, +41, 26.869881741702557, 1.6368354177457138e-53, +41, 27.50923865288496, 5.3714024253680684e-54, +41, 27.509238660335541, 5.371403525428115e-54, +41, 28.142790779471397, 1.8614995765867043e-54, +41, 28.142790786921978, 1.8614993186913763e-54, +41, 28.770478524267673, 6.8010686240834692e-55, +41, 28.770478531718254, 6.8010665157488161e-55, +41, 29.392237104475498, 2.6151090463060908e-55, +41, 29.392237111926079, 2.6151083985090659e-55, +41, 30.00799672305584, 1.0564964051943473e-55, +41, 30.00799673050642, 1.0564965558976623e-55, +41, 30.617682799696922, 4.4769434240746522e-56, +41, 30.617682807147503, 4.476941847194843e-56, +41, 31.221216365695, 1.9865352596664337e-56, +41, 31.22121637314558, 1.9865355524875975e-56, +41, 31.818514481186867, 9.2159451402794094e-57, +41, 31.818514488637447, 9.2159466688116338e-57, +41, 32.409490957856178, 4.4613696997625097e-57, +41, 32.409490965306759, 4.4613679528438168e-57, +41, 32.994057275354862, 2.2495337343609451e-57, +41, 32.994057282805443, 2.2495336072907286e-57, +41, 33.572123780846596, 1.179515303712195e-57, +41, 33.572123788297176, 1.1795156958792046e-57, +41, 34.14360136538744, 6.4199511051895594e-58, +41, 34.14360137283802, 6.4199510962157903e-58, +41, 34.708403661847115, 3.6178146943975811e-58, +41, 34.708403669297695, 3.6178147081673786e-58, +41, 35.266449868679047, 2.1062679049212825e-58, +41, 35.266449876129627, 2.1062685252617971e-58, +41, 35.817668430507183, 1.2639711870312449e-58, +41, 35.817668437957764, 1.2639716152935793e-58, +41, 36.362001702189445, 7.8141248205685345e-59, +41, 36.362001709640026, 7.8141256095820112e-59, +41, 36.899411715567112, 4.9591961766203501e-59, +41, 36.899411723017693, 4.9591939834951158e-59, +41, 37.429887130856514, 3.2171228324064162e-59, +41, 37.429887138307095, 3.2171241631281812e-59, +41, 37.953451178967953, 2.1269491341026847e-59, +41, 37.953451186418533, 2.1269492501039519e-59, +41, 38.470170341432095, 1.4286189358117899e-59, +41, 38.470170348882675, 1.4286192796461194e-59, +41, 38.980162680149078, 9.7171129843050171e-60, +41, 38.980162687599659, 9.7171121503283134e-60, +41, 39.4836046397686, 6.6707774251818163e-60, +41, 39.483604647219181, 6.6707772095156799e-60, +41, 39.980734407901764, 4.6551475379699454e-60, +41, 39.980734415352345, 4.6551461775452092e-60, +41, 40.471850238740444, 3.2996303654595619e-60, +41, 40.471850246191025, 3.299629164010922e-60, +41, 40.957302808761597, 2.3382554940028968e-60, +41, 40.957302816212177, 2.3382555227359038e-60, +41, 41.437482245266438, 1.6521789716672249e-60, +41, 41.437482252717018, 1.6521799531621949e-60, +41, 41.912801884114742, 1.161253768520295e-60, +41, 41.912801891565323, 1.161254060902467e-60, +42, 0.80278279632329941, 6.9226590222761392e-09, +42, 0.80278280377388, 6.9226375602766169e-09, +42, 1.6720976755023003, 5.4292207524054341e-12, +42, 1.6720976829528809, 5.4292105857191855e-12, +42, 2.529393844306469, 9.4401492831892214e-15, +42, 2.5293938517570496, 9.440137562058038e-15, +42, 3.3761483952403069, 2.9133785168914818e-17, +42, 3.3761484026908875, 2.913375858396887e-17, +42, 4.2133949920535088, 1.4111373398855075e-19, +42, 4.2133949995040894, 1.4111362180318768e-19, +42, 5.0418881699442863, 9.9130527366678168e-22, +42, 5.0418881773948669, 9.9130466763312262e-22, +42, 5.8622036203742027, 9.5571596865742465e-24, +42, 5.8622036278247833, 9.557157157815258e-24, +42, 6.6747959107160568, 1.2138894993380412e-25, +42, 6.6747959181666374, 1.2138890999121016e-25, +42, 7.4800334572792053, 1.9681951625914627e-27, +42, 7.4800334647297859, 1.9681946847574354e-27, +42, 8.2782208025455475, 3.9729393004208446e-29, +42, 8.2782208099961281, 3.9729377246408213e-29, +42, 9.0696135759353638, 9.7824189185222744e-31, +42, 9.0696135833859444, 9.782415933019014e-31, +42, 9.854428842663765, 2.8887602415935609e-32, +42, 9.8544288501143456, 2.8887597673727744e-32, +42, 10.63285256922245, 1.0085526144203417e-33, +42, 10.632852576673031, 1.0085524424097982e-33, +42, 11.405045129358768, 4.1124264530225136e-35, +42, 11.405045136809349, 4.1124259662087623e-35, +42, 12.171145439147949, 1.9378425726639904e-36, +42, 12.17114544659853, 1.9378423676609656e-36, +42, 12.931274153292179, 1.045559969037066e-37, +42, 12.93127416074276, 1.0455596177818872e-37, +42, 13.685536183416843, 6.4070132508159121e-39, +42, 13.685536190867424, 6.407013282659424e-39, +42, 14.43402262032032, 4.4269253093815454e-40, +42, 14.434022627770901, 4.4269241541282206e-40, +42, 15.176812402904034, 3.4267679212328663e-41, +42, 15.176812410354614, 3.4267674343162701e-41, +42, 15.913973532617092, 2.9544897572847338e-42, +42, 15.913973540067673, 2.9544887105567143e-42, +42, 16.645564183592796, 2.8223839882129309e-43, +42, 16.645564191043377, 2.8223832928604173e-43, +42, 17.371633522212505, 2.9731354185298358e-44, +42, 17.371633529663086, 2.9731344508034859e-44, +42, 18.092222459614277, 3.4386472737376164e-45, +42, 18.092222467064857, 3.438646475084569e-45, +42, 18.807364217936993, 4.3491258313818515e-46, +42, 18.807364225387573, 4.3491245093441195e-46, +42, 19.517084851861, 5.9932507487453098e-47, +42, 19.517084859311581, 5.9932510605416288e-47, +42, 20.221403621137142, 8.9680022145373332e-48, +42, 20.221403628587723, 8.9680030564321489e-48, +42, 20.920333370566368, 1.4525643162552315e-48, +42, 20.920333378016949, 1.4525644551988813e-48, +42, 21.613880790770054, 2.5392779271460697e-49, +42, 21.613880798220634, 2.5392781202855432e-49, +42, 22.302046649158001, 4.7778624747879543e-50, +42, 22.302046656608582, 4.7778609688180624e-50, +42, 22.984826005995274, 9.6514724249543887e-51, +42, 22.984826013445854, 9.6514719380202041e-51, +42, 23.662208318710327, 2.0880714410437191e-51, +42, 23.662208326160908, 2.0880713844950678e-51, +42, 24.334177613258362, 4.8272884627393777e-52, +42, 24.334177620708942, 4.827289071207131e-52, +42, 25.000712551176548, 1.1899655825914922e-52, +42, 25.000712558627129, 1.1899654828045305e-52, +42, 25.661786533892155, 3.1214193463127235e-53, +42, 25.661786541342735, 3.1214189097750331e-53, +42, 26.317367739975452, 8.6958244653446017e-54, +42, 26.317367747426033, 8.6958215737634595e-54, +42, 26.967419199645519, 2.568029364046961e-54, +42, 26.9674192070961, 2.568029072939054e-54, +42, 27.611898817121983, 8.0249111457810081e-55, +42, 27.611898824572563, 8.0249107539069643e-55, +42, 28.250759445130825, 2.6489724041957653e-55, +42, 28.250759452581406, 2.6489725573532699e-55, +42, 28.883948929607868, 9.2210130457023447e-56, +42, 28.883948937058449, 9.221012553865369e-56, +42, 29.51141019910574, 3.3793032788582558e-56, +42, 29.51141020655632, 3.3793020931771187e-56, +42, 30.133081384003162, 1.3017207647702263e-56, +42, 30.133081391453743, 1.3017209766503453e-56, +42, 30.748895935714245, 5.2620269591213157e-57, +42, 30.748895943164825, 5.2620264324839771e-57, +42, 31.358782909810543, 2.2286239885660763e-57, +42, 31.358782917261124, 2.2286233962325355e-57, +42, 31.962667249143124, 9.8734765335665241e-58, +42, 31.962667256593704, 9.8734771638543485e-58, +42, 32.560470215976238, 4.5689315053016582e-58, +42, 32.560470223426819, 4.5689315012563647e-58, +42, 33.152110017836094, 2.204279572077455e-58, +42, 33.152110025286674, 2.2042786952183643e-58, +42, 33.737502619624138, 1.1068187252756619e-58, +42, 33.737502627074718, 1.1068183477512304e-58, +42, 34.316562816500664, 5.7749063078169861e-59, +42, 34.316562823951244, 5.7749039481390523e-59, +42, 34.88920570909977, 3.1261765683062832e-59, +42, 34.88920571655035, 3.1261767380643983e-59, +42, 35.455348581075668, 1.7513391881906954e-59, +42, 35.455348588526249, 1.7513391738815631e-59, +42, 36.014913402497768, 1.0132955667514977e-59, +42, 36.014913409948349, 1.0132953554711642e-59, +42, 36.567829996347427, 6.0419225386156667e-60, +42, 36.567830003798008, 6.0419249645517703e-60, +42, 37.114040024578571, 3.7084880489823353e-60, +42, 37.114040032029152, 3.70848786570471e-60, +42, 37.653502009809017, 2.338854994512836e-60, +42, 37.653502017259598, 2.3388544174312297e-60, +42, 38.18619729578495, 1.5082771906917482e-60, +42, 38.186197303235531, 1.5082768335011839e-60, +42, 38.712137028574944, 9.9179507405724581e-61, +42, 38.712137036025524, 9.9179533842514018e-61, +42, 39.231369808316231, 6.6305438401582333e-61, +42, 39.231369815766811, 6.6305466146285408e-61, +42, 39.743989452719688, 4.4929623334862857e-61, +42, 39.743989460170269, 4.4929644560224335e-61, +42, 40.250141784548759, 3.0762046694284016e-61, +42, 40.25014179199934, 3.0762050675393587e-61, +42, 40.750029072165489, 2.1232133872540221e-61, +42, 40.75002907961607, 2.1232143184545875e-61, +42, 41.243910521268845, 1.5040992206787617e-61, +42, 41.243910528719425, 1.5040994366927394e-61, +42, 41.732097789645195, 1.066568753779962e-61, +42, 41.732097797095776, 1.0665688191693734e-61, +42, 42.21494534611702, 7.5520351086269267e-62, +42, 42.2149453535676, 7.5520324461586611e-62, +42, 42.692836992442608, 5.3257794840175116e-62, +42, 42.692836999893188, 5.3257796543161497e-62, +43, 0.80374263972043991, 6.2265229208281086e-09, +43, 0.80374264717102051, 6.2265021676836063e-09, +43, 1.6738473474979401, 4.6500497846984813e-12, +43, 1.6738473549485207, 4.6500437983955095e-12, +43, 2.5320717096328735, 7.6999297251521244e-15, +43, 2.5320717170834541, 7.6999200444794929e-15, +43, 3.3798806890845299, 2.2631148188373452e-17, +43, 3.3798806965351105, 2.2631134624768674e-17, +43, 4.2182994857430458, 1.0439730347593901e-19, +43, 4.2182994931936264, 1.0439725582552017e-19, +43, 5.0480765253305435, 6.9846384600905826e-22, +43, 5.0480765327811241, 6.9846329992999297e-22, +43, 5.8697829768061638, 6.4133648817528039e-24, +43, 5.8697829842567444, 6.4133622301576819e-24, +43, 6.6838699728250504, 7.7581908507981851e-26, +43, 6.683869980275631, 7.7581869040059224e-26, +43, 7.4907033443450928, 1.1980536998817066e-27, +43, 7.4907033517956734, 1.1980533287085893e-27, +43, 8.2905857041478157, 2.3032904037204204e-29, +43, 8.2905857115983963, 2.3032899434237301e-29, +43, 9.0837712809443474, 5.4014825819620076e-31, +43, 9.083771288394928, 5.4014818234672467e-31, +43, 9.8704762011766434, 1.5191783549612291e-32, +43, 9.870476208627224, 1.519177820284746e-32, +43, 10.650885902345181, 5.0515644746481509e-34, +43, 10.650885909795761, 5.0515633182229788e-34, +43, 11.425160549581051, 1.9618008332053675e-35, +43, 11.425160557031631, 1.9618004402996259e-35, +43, 12.193439178168774, 8.8044787784929281e-37, +43, 12.193439185619354, 8.8044753063642099e-37, +43, 12.955842867493629, 4.524398586238088e-38, +43, 12.95584287494421, 4.5243971572220065e-38, +43, 13.712477192282677, 2.6405415266954578e-39, +43, 13.712477199733257, 2.6405409196625623e-39, +43, 14.463434211909771, 1.7376536138713058e-40, +43, 14.463434219360352, 1.7376535898353172e-40, +43, 15.20879402756691, 1.2810567130050931e-41, +43, 15.20879403501749, 1.2810562769780531e-41, +43, 15.948626108467579, 1.0519315407923782e-42, +43, 15.948626115918159, 1.0519312156263242e-42, +43, 16.682990290224552, 9.5706606808167989e-44, +43, 16.682990297675133, 9.5706595162643238e-44, +43, 17.411937654018402, 9.6019964557800178e-45, +43, 17.411937661468983, 9.6019932159219121e-45, +43, 18.13551127165556, 1.0576852894588731e-45, +43, 18.13551127910614, 1.0576850398218628e-45, +43, 18.853746756911278, 1.2740748320858259e-46, +43, 18.853746764361858, 1.2740744275602638e-46, +43, 19.566672801971436, 1.6721803291553602e-47, +43, 19.566672809422016, 1.6721802496179909e-47, +43, 20.274311557412148, 2.3831385055210507e-48, +43, 20.274311564862728, 2.383138722927918e-48, +43, 20.976678997278214, 3.6764564183028991e-49, +43, 20.976679004728794, 3.6764551742830879e-49, +43, 21.673785232007504, 6.1214527112754142e-50, +43, 21.673785239458084, 6.1214517381911048e-50, +43, 22.365634694695473, 1.0970868259989562e-50, +43, 22.365634702146053, 1.0970869292873099e-50, +43, 23.052226364612579, 2.1109654457950782e-51, +43, 23.05222637206316, 2.1109648351815291e-51, +43, 23.73355396091938, 4.3504475736244337e-52, +43, 23.733553968369961, 4.3504474174699854e-52, +43, 24.409606009721756, 9.5811885685959652e-53, +43, 24.409606017172337, 9.5811865620694161e-53, +43, 25.080366007983685, 2.2501451275878645e-53, +43, 25.080366015434265, 2.250144411912722e-53, +43, 25.745812483131886, 5.6237768952562137e-54, +43, 25.745812490582466, 5.6237769737644979e-54, +43, 26.405919045209885, 1.4929156510239942e-54, +43, 26.405919052660465, 1.4929154295863137e-54, +43, 27.060654483735561, 4.2017660690891096e-55, +43, 27.060654491186142, 4.2017661352698133e-55, +43, 27.70998277515173, 1.2515559328727676e-55, +43, 27.70998278260231, 1.2515561411826354e-55, +43, 28.353863142430782, 3.9386790330335798e-56, +43, 28.353863149881363, 3.938678699998805e-56, +43, 28.992250114679337, 1.30742297126559e-56, +43, 28.992250122129917, 1.3074227853186405e-56, +43, 29.625093564391136, 4.5703490079865401e-57, +43, 29.625093571841717, 4.5703489945165746e-57, +43, 30.252338789403439, 1.679839691186224e-57, +43, 30.252338796854019, 1.6798400103101351e-57, +43, 30.873926617205143, 6.4818615616990382e-58, +43, 30.873926624655724, 6.4818617121955273e-58, +43, 31.489793568849564, 2.6216783109665946e-58, +43, 31.489793576300144, 2.621678842878726e-58, +43, 32.099872037768364, 1.1097966007180264e-58, +43, 32.099872045218945, 1.1097965164251156e-58, +43, 32.704090610146523, 4.9093647055745871e-59, +43, 32.704090617597103, 4.9093629238590932e-59, +43, 33.302374452352524, 2.2663027175130519e-59, +43, 33.302374459803104, 2.2663030381968129e-59, +43, 33.894645825028419, 1.089821777981862e-59, +43, 33.894645832479, 1.0898215996640809e-59, +43, 34.480824865400791, 5.4503470421960063e-60, +43, 34.480824872851372, 5.4503475216165703e-60, +43, 35.060830503702164, 2.8302994788743613e-60, +43, 35.060830511152744, 2.8302993299817642e-60, +43, 35.634581781923771, 1.5241498107793508e-60, +43, 35.634581789374352, 1.524150366688098e-60, +43, 36.201999485492706, 8.4901039478581528e-61, +43, 36.201999492943287, 8.4901057099943408e-61, +43, 36.763008333742619, 4.8826921073920482e-61, +43, 36.763008341193199, 4.88269148765274e-61, +43, 37.317539721727371, 2.89325097146544e-61, +43, 37.317539729177952, 2.8932501406101497e-61, +43, 37.865535192191601, 1.763384563649848e-61, +43, 37.865535199642181, 1.763384206032246e-61, +43, 38.406950734555721, 1.1052474884369675e-61, +43, 38.406950742006302, 1.1052472149923624e-61, +43, 38.941761992871761, 7.0853082671685455e-62, +43, 38.941762000322342, 7.0853089890115881e-62, +43, 39.46997033059597, 4.6335481062213602e-62, +43, 39.469970338046551, 4.6335497917407068e-62, +43, 39.991609625518322, 3.0826746406189898e-62, +43, 39.991609632968903, 3.0826749253707252e-62, +43, 40.506753340363503, 2.0804026345727385e-62, +43, 40.506753347814083, 2.0804017787903443e-62, +43, 41.015521101653576, 1.4200099809529536e-62, +43, 41.015521109104156, 1.420009712483586e-62, +43, 41.518083661794662, 9.7731968830010019e-63, +43, 41.518083669245243, 9.7731991835116888e-63, +43, 42.014664947986603, 6.8583190565524262e-63, +43, 42.014664955437183, 6.8583151787402871e-63, +43, 42.505540028214455, 4.8636242162072754e-63, +43, 42.505540035665035, 4.8636220226399413e-63, +43, 42.991028398275375, 3.448316649423409e-63, +43, 42.991028405725956, 3.4483150726159365e-63, +43, 43.471483275294304, 2.4381653298784023e-63, +43, 43.471483282744884, 2.4381645543034918e-63, +43, 43.947278343141079, 1.7155393308219594e-63, +43, 43.94727835059166, 1.7155397584796518e-63, +44, 0.80467161536216736, 5.6136778930781251e-09, +44, 0.80467162281274796, 5.6136608371297985e-09, +44, 1.6755395382642746, 3.996456677211653e-12, +44, 1.6755395457148552, 3.996449766244987e-12, +44, 2.5346603021025658, 6.3089402910587147e-15, +44, 2.5346603095531464, 6.308934747725832e-15, +44, 3.3834870904684067, 1.7678471267789971e-17, +44, 3.3834870979189873, 1.7678457325653622e-17, +44, 4.2230369374155998, 7.7750648421336081e-20, +44, 4.2230369448661804, 7.775059336381719e-20, +44, 5.0540523454546928, 4.9595393901990306e-22, +44, 5.0540523529052734, 4.9595359464101014e-22, +44, 5.8771000504493713, 4.3418177822464477e-24, +44, 5.8771000578999519, 4.3418159986033655e-24, +44, 6.692627839744091, 5.0077047309676213e-26, +44, 6.6926278471946716, 5.0077018300841822e-26, +44, 7.5009989961981773, 7.3731092712775596e-28, +44, 7.5009990036487579, 7.3731071442298436e-28, +44, 8.3025142028927803, 1.35151930219129e-29, +44, 8.3025142103433609, 1.3515188596538854e-29, +44, 9.0974262878298759, 3.0219530142929182e-31, +44, 9.0974262952804565, 3.0219525157972958e-31, +44, 9.885950393974781, 8.1037515418772692e-33, +44, 9.8859504014253616, 8.1037496721190902e-33, +44, 10.668271347880363, 2.5692524853802503e-34, +44, 10.668271355330944, 2.5692522872428457e-34, +44, 11.444549031555653, 9.5134883272533602e-36, +44, 11.444549039006233, 9.5134851368063353e-36, +44, 12.214922517538071, 4.0709150121215076e-37, +44, 12.214922524988651, 4.0709145082759209e-37, +44, 12.9795131534338, 1.9945846540912174e-38, +44, 12.97951316088438, 1.9945845789467207e-38, +44, 13.738427057862282, 1.1099089234391263e-39, +44, 13.738427065312862, 1.1099085251966313e-39, +44, 14.491757087409496, 6.9640101710065686e-41, +44, 14.491757094860077, 6.9640078677027602e-41, +44, 15.239584363996983, 4.8951439415325917e-42, +44, 15.239584371447563, 4.8951421880711173e-42, +44, 15.981979586184025, 3.8325250997128576e-43, +44, 15.981979593634605, 3.8325246691666718e-43, +44, 16.719004042446613, 3.3246034933715899e-44, +44, 16.719004049897194, 3.3246028367467908e-44, +44, 17.450710512697697, 3.1802402277522236e-45, +44, 17.450710520148277, 3.1802402020461697e-45, +44, 18.177143938839436, 3.3400774233097505e-46, +44, 18.177143946290016, 3.3400767496533442e-46, +44, 18.898342065513134, 3.8361752046986516e-47, +44, 18.898342072963715, 3.8361742569729389e-47, +44, 19.614335909485817, 4.800572916017465e-48, +44, 19.614335916936398, 4.8005724839761991e-48, +44, 20.325150176882744, 6.5233421352255798e-49, +44, 20.325150184333324, 6.5233403168874937e-49, +44, 21.030803643167019, 9.5954871171553862e-50, +44, 21.030803650617599, 9.5954850050970341e-50, +44, 21.731309413909912, 1.5234114031559522e-50, +44, 21.731309421360493, 1.5234111451311826e-50, +44, 22.42667518556118, 2.6033920081158185e-51, +44, 22.426675193011761, 2.6033911145943002e-51, +44, 23.116903461515903, 4.7767105988238726e-52, +44, 23.116903468966484, 4.7767099043402472e-52, +44, 23.801991693675518, 9.387467949055562e-53, +44, 23.801991701126099, 9.3874684263904844e-53, +44, 24.481932438910007, 1.971615201422645e-53, +44, 24.481932446360588, 1.9716152109831415e-53, +44, 25.156713478267193, 4.4159911548218363e-54, +44, 25.156713485717773, 4.4159913675159231e-54, +44, 25.826317891478539, 1.0526730104836363e-54, +44, 25.826317898929119, 1.0526729250930486e-54, +44, 26.490724146366119, 2.6655572078148186e-55, +44, 26.4907241538167, 2.6655568543053462e-55, +44, 27.149906150996685, 7.1568186823845456e-56, +44, 27.149906158447266, 7.1568199199919761e-56, +44, 27.803833283483982, 2.0339107389822583e-56, +44, 27.803833290934563, 2.0339100579837449e-56, +44, 28.452470488846302, 6.1079388232656124e-57, +44, 28.452470496296883, 6.1079379800803341e-57, +44, 29.095778256654739, 1.9351084823971883e-57, +44, 29.09577826410532, 1.9351087848232976e-57, +44, 29.733712695538998, 6.4577619511222403e-58, +44, 29.733712702989578, 6.4577623280174925e-58, +44, 30.366225592792034, 2.2665241394008965e-58, +44, 30.366225600242615, 2.2665233610200225e-58, +44, 30.993264488875866, 8.3538981878075504e-59, +44, 30.993264496326447, 8.3538973902278832e-59, +44, 31.614772744476795, 3.228699802800217e-59, +44, 31.614772751927376, 3.2286992972912687e-59, +44, 32.230689719319344, 1.3065931274581666e-59, +44, 32.230689726769924, 1.3065932206329812e-59, +44, 32.840950936079025, 5.5283283462661653e-60, +44, 32.840950943529606, 5.5283297905073914e-60, +44, 33.445488356053829, 2.4420363935005462e-60, +44, 33.44548836350441, 2.4420365090235068e-60, +44, 34.044230751693249, 1.1247018428087803e-60, +44, 34.044230759143829, 1.1247019447882527e-60, +44, 34.637104175984859, 5.3916101329900339e-61, +44, 34.63710418343544, 5.3916117966603539e-61, +44, 35.224032618105412, 2.6860578423081937e-61, +44, 35.224032625555992, 2.6860582812593381e-61, +44, 35.80493887513876, 1.3884862436203571e-61, +44, 35.80493888258934, 1.3884857125492079e-61, +44, 36.379745692014694, 7.4395293787923654e-62, +44, 36.379745699465275, 7.439531573426712e-62, +44, 36.948377177119255, 4.1213785665077009e-62, +44, 36.948377184569836, 4.1213775271898848e-62, +44, 37.510760769248009, 2.3563995586116442e-62, +44, 37.510760776698589, 2.3563998572726389e-62, +44, 38.066829569637775, 1.387825922758731e-62, +44, 38.066829577088356, 1.3878263222132413e-62, +44, 38.616525396704674, 8.4026868409755843e-63, +44, 38.616525404155254, 8.4026849826191917e-63, +44, 39.15980252623558, 5.2330380914494507e-63, +44, 39.159802533686161, 5.2330384337581212e-63, +44, 39.696632169187069, 3.334915925394798e-63, +44, 39.69663217663765, 3.3349150946973438e-63, +44, 40.227007821202278, 2.1688592245996604e-63, +44, 40.227007828652859, 2.1688582534753389e-63, +44, 40.750951237976551, 1.4357225842013951e-63, +44, 40.750951245427132, 1.4357220404846224e-63, +44, 41.268518827855587, 9.6476907882532163e-64, +44, 41.268518835306168, 9.6476938144334747e-64, +44, 41.779807850718498, 6.5625953469000859e-64, +44, 41.779807858169079, 6.5625937860509035e-64, +44, 42.284961640834808, 4.5058398148726142e-64, +44, 42.284961648285389, 4.5058416997625145e-64, +44, 42.784172587096691, 3.129001741872849e-64, +44, 42.784172594547272, 3.1290032694075403e-64, +44, 43.277681954205036, 2.2178639138343572e-64, +44, 43.277681961655617, 2.217862574017806e-64, +44, 43.765775695443153, 1.5734475453107395e-64, +44, 43.765775702893734, 1.5734473760285837e-64, +44, 44.248776264488697, 1.1146763587781778e-64, +44, 44.248776271939278, 1.1146759216720561e-64, +44, 44.72703155875206, 7.8671948445613079e-65, +44, 44.727031566202641, 7.8671929349871774e-65, +45, 0.80557141453027725, 5.0726413534345763e-09, +45, 0.80557142198085785, 5.0726286490438008e-09, +45, 1.6771774515509605, 3.4460674497709128e-12, +45, 1.6771774590015411, 3.4460610672915812e-12, +45, 2.5371646136045456, 5.1916332019115706e-15, +45, 2.5371646210551262, 5.1916266282356591e-15, +45, 3.3869747146964073, 1.388371209350898e-17, +45, 3.3869747221469879, 1.3883700616973645e-17, +45, 4.2276168465614319, 5.8275697184933708e-20, +45, 4.2276168540120125, 5.8275654750778e-20, +45, 5.0598277673125267, 3.5477579887516431e-22, +45, 5.0598277747631073, 3.5477564975097925e-22, +45, 5.8841698914766312, 2.9642841271070067e-24, +45, 5.8841698989272118, 2.9642822863171458e-24, +45, 6.7010877579450607, 3.2630738774830459e-26, +45, 6.7010877653956413, 3.263073017156076e-26, +45, 7.5109421014785767, 4.5854715121871508e-28, +45, 7.5109421089291573, 4.5854688992980262e-28, +45, 8.3140317350625992, 8.0223903144934105e-30, +45, 8.3140317425131798, 8.0223889424453224e-30, +45, 9.1106080338358879, 1.7120675939027816e-31, +45, 9.1106080412864685, 1.7120672151200833e-31, +45, 9.9008851423859596, 4.3820095981211352e-33, +45, 9.9008851498365402, 4.3820077220180574e-33, +45, 10.68504723161459, 1.3260186203855025e-34, +45, 10.68504723906517, 1.3260184368382346e-34, +45, 11.463253825902939, 4.6864022295376335e-36, +45, 11.463253833353519, 4.6864003438291794e-36, +45, 12.235643930733204, 1.9140332469174886e-37, +45, 12.235643938183784, 1.9140329245548746e-37, +45, 13.002339072525501, 8.9509286929604941e-39, +45, 13.002339079976082, 8.9509255547380081e-39, +45, 13.763445809483528, 4.7540198232627669e-40, +45, 13.763445816934109, 4.754018125249747e-40, +45, 14.519057631492615, 2.8470235348619623e-41, +45, 14.519057638943195, 2.8470231939414067e-41, +45, 15.269256517291069, 1.9100959307121379e-42, +45, 15.26925652474165, 1.9100954215055896e-42, +45, 16.014114238321781, 1.4273575426163056e-43, +45, 16.014114245772362, 1.4273572183784119e-43, +45, 16.753693364560604, 1.1818045387769778e-44, +45, 16.753693372011185, 1.1818045406989631e-44, +45, 17.488048121333122, 1.0790078448072891e-45, +45, 17.488048128783703, 1.0790075019516635e-45, +45, 18.217225149273872, 1.0816351664675249e-46, +45, 18.217225156724453, 1.0816350186856221e-46, +45, 18.941264040768147, 1.1857252783860139e-47, +45, 18.941264048218727, 1.1857253231470769e-47, +45, 19.660197868943214, 1.4162599457171879e-48, +45, 19.660197876393795, 1.4162594722619744e-48, +45, 20.374053634703159, 1.8369095424586302e-49, +45, 20.37405364215374, 1.8369090653707792e-49, +45, 21.082852572202682, 2.5790366146060495e-50, +45, 21.082852579653263, 2.5790364403184686e-50, +45, 21.786610469222069, 3.9082959513144336e-51, +45, 21.786610476672649, 3.9082953206667202e-51, +45, 22.485337935388088, 6.3752648464290151e-52, +45, 22.485337942838669, 6.3752654487505152e-52, +45, 23.17904057353735, 1.1165741627665863e-52, +45, 23.17904058098793, 1.1165741068514325e-52, +45, 23.867719195783138, 2.0946976196525122e-53, +45, 23.867719203233719, 2.0946972972903319e-53, +45, 24.551369942724705, 4.199784043907654e-54, +45, 24.551369950175285, 4.1997830354107881e-54, +45, 25.229984417557716, 8.9802156001108849e-55, +45, 25.229984425008297, 8.9802170199891646e-55, +45, 25.903549753129482, 2.0437739932039704e-55, +45, 25.903549760580063, 2.0437737107632989e-55, +45, 26.572048746049404, 4.9412956452360819e-56, +45, 26.572048753499985, 4.9412949268715549e-56, +45, 27.235459871590137, 1.266852119595342e-56, +45, 27.235459879040718, 1.266851943610651e-56, +45, 27.893757358193398, 3.4382556738087285e-57, +45, 27.893757365643978, 3.4382553299106011e-57, +45, 28.546911224722862, 9.8618508840267625e-58, +45, 28.546911232173443, 9.8618491033618367e-58, +45, 29.194887325167656, 2.9846563929548203e-58, +45, 29.194887332618237, 2.9846556456038703e-58, +45, 29.837647385895252, 9.5164851985855428e-59, +45, 29.837647393345833, 9.5164859067162488e-59, +45, 30.475149028003216, 3.1919471145235652e-59, +45, 30.475149035453796, 3.1919465385262668e-59, +45, 31.10734585672617, 1.1245990945651224e-59, +45, 31.10734586417675, 1.1245987676615756e-59, +45, 31.734187498688698, 4.156056326015243e-60, +45, 31.734187506139278, 4.1560548844122152e-60, +45, 32.355619706213474, 1.6087715958830335e-60, +45, 32.355619713664055, 1.6087709778691514e-60, +45, 32.971584491431713, 6.5137250453975497e-61, +45, 32.971584498882294, 6.513725581556009e-61, +45, 33.582020282745361, 2.7547442749945884e-61, +45, 33.582020290195942, 2.754744536546609e-61, +45, 34.186862200498581, 1.2151842423090292e-61, +45, 34.186862207949162, 1.2151844807083802e-61, +45, 34.786042362451553, 5.5842073878826692e-62, +45, 34.786042369902134, 5.584208841716622e-62, +45, 35.379490330815315, 2.668953446148253e-62, +45, 35.379490338265896, 2.6689534358362321e-62, +45, 35.967133708298206, 1.3247417718966731e-62, +45, 35.967133715748787, 1.3247418233453314e-62, +45, 36.54889889061451, 6.81830654860711e-63, +45, 36.54889889806509, 6.818308174202415e-63, +45, 37.124712072312832, 3.6352982698527776e-63, +45, 37.124712079763412, 3.6352977649621008e-63, +45, 37.69450056552887, 2.0032179772713561e-63, +45, 37.69450057297945, 2.0032182198683058e-63, +45, 38.258194424211979, 1.1388655591516622e-63, +45, 38.25819443166256, 1.1388660071209926e-63, +45, 38.815728560090065, 6.6679019732380082e-64, +45, 38.815728567540646, 6.6678989599996421e-64, +45, 39.367045409977436, 4.0127865735433081e-64, +45, 39.367045417428017, 4.0127869714530915e-64, +45, 39.912098117172718, 2.4823303830602347e-64, +45, 39.912098124623299, 2.4823303478495604e-64, +45, 40.450854524970055, 1.5726807857647126e-64, +45, 40.450854532420635, 1.572680157861683e-64, +45, 40.983301803469658, 1.0171102749116892e-64, +45, 40.983301810920238, 1.0171100325088395e-64, +45, 41.509451732039452, 6.6986541124123709e-65, +45, 41.509451739490032, 6.698656106772216e-65, +45, 42.029346436262131, 4.4811565030652948e-65, +45, 42.029346443712711, 4.4811552128179833e-65, +45, 42.543064199388027, 3.0368532731017174e-65, +45, 42.543064206838608, 3.0368549286644374e-65, +45, 43.050724543631077, 2.0792657453220576e-65, +45, 43.050724551081657, 2.0792648606503151e-65, +45, 43.552491940557957, 1.4343039408147246e-65, +45, 43.552491948008537, 1.4343037745621818e-65, +45, 44.048576854169369, 1.0116281113567898e-65, +45, 44.048576861619949, 1.0116281946112367e-65, +45, 44.539233565330505, 7.1772181026542797e-66, +45, 44.539233572781086, 7.1772152894419919e-66, +45, 45.024754360318184, 5.0910329745997959e-66, +45, 45.024754367768764, 5.0910353852429258e-66, +45, 45.505460530519485, 3.6018564323451954e-66, +45, 45.505460537970066, 3.6018566644727318e-66, +46, 0.80644359439611435, 4.5937276590999757e-09, +46, 0.80644360184669495, 4.5937132947588083e-09, +46, 1.6787640303373337, 2.98087274959071e-12, +46, 1.6787640377879143, 2.9808661935097509e-12, +46, 2.5395892709493637, 4.2899194266498207e-15, +46, 2.5395892783999443, 4.2899128733913176e-15, +46, 3.3903501108288765, 1.0959512621942293e-17, +46, 3.3903501182794571, 1.0959500272092307e-17, +46, 4.2320479527115822, 4.3946338657974935e-20, +46, 4.2320479601621628, 4.3946295614372081e-20, +46, 5.0654139667749405, 2.5559124327100822e-22, +46, 5.0654139742255211, 2.5559109015816517e-22, +46, 5.8910063803195953, 2.0402090976949595e-24, +46, 5.8910063877701759, 2.0402082133441809e-24, +46, 6.7092665061354637, 2.145610870292747e-26, +46, 6.7092665135860443, 2.1456095483082796e-26, +46, 7.5205526426434517, 2.8805916737655836e-28, +46, 7.5205526500940323, 2.8805901581525201e-28, +46, 8.3251616805791855, 4.8148199932649022e-30, +46, 8.3251616880297661, 4.8148180062818176e-30, +46, 9.1233435869216919, 9.8170133416748883e-32, +46, 9.1233435943722725, 9.8170091250383215e-32, +46, 9.9153114706277847, 2.4005845709495377e-33, +46, 9.9153114780783653, 2.4005840292112442e-33, +46, 10.701248779892921, 6.9403518737356291e-35, +46, 10.701248787343502, 6.9403506658677479e-35, +46, 11.481314651668072, 2.3434809696862083e-36, +46, 11.481314659118652, 2.3434804155032999e-36, +46, 12.255647927522659, 9.1445672766592834e-38, +46, 12.25564793497324, 9.144564597736229e-38, +46, 13.024370245635509, 4.0857760701521376e-39, +46, 13.02437025308609, 4.0857744961794638e-39, +46, 13.787588477134705, 2.0732944897302441e-40, +46, 13.787588484585285, 2.0732942157647581e-40, +46, 14.545396625995636, 1.1862751290774051e-41, +46, 14.545396633446217, 1.1862750069296983e-41, +46, 15.297877408564091, 7.6040389545684135e-43, +46, 15.297877416014671, 7.6040366169514959e-43, +46, 16.045103512704372, 5.4289663713334323e-44, +46, 16.045103520154953, 5.4289651014099083e-44, +46, 16.787138611078262, 4.2946308014331587e-45, +46, 16.787138618528843, 4.2946309393062078e-45, +46, 17.524038217961788, 3.7462898475103639e-46, +46, 17.524038225412369, 3.7462891712075553e-46, +46, 18.255850434303284, 3.5880254135208017e-47, +46, 18.255850441753864, 3.5880241641149892e-47, +46, 18.982616521418095, 3.7580124520341846e-48, +46, 18.982616528868675, 3.7580126105590187e-48, +46, 19.704371377825737, 4.2886328507162675e-49, +46, 19.704371385276318, 4.2886330882959628e-49, +46, 20.421144008636475, 5.3145793544475191e-50, +46, 20.421144016087055, 5.3145791023640892e-50, +46, 21.132957860827446, 7.129322161861212e-51, +46, 21.132957868278027, 7.1293220408739578e-51, +46, 21.839831113815308, 1.0322705745422839e-51, +46, 21.839831121265888, 1.0322702541941654e-51, +46, 22.541776970028877, 1.6088924619052019e-52, +46, 22.541776977479458, 1.6088926207793541e-52, +46, 23.238803811371326, 2.6924552321776528e-53, +46, 23.238803818821907, 2.6924555089976417e-53, +46, 23.93091543763876, 4.8264330441793963e-54, +46, 23.93091544508934, 4.8264333299674338e-54, +46, 24.618111185729504, 9.2467851317038458e-55, +46, 24.618111193180084, 9.246783397684182e-55, +46, 25.300386071205139, 1.8894165539320044e-55, +46, 25.30038607865572, 1.8894160802674772e-55, +46, 25.977730877697468, 4.1093484735817205e-56, +46, 25.977730885148048, 4.1093479284602969e-56, +46, 26.650132246315479, 9.4952675622529843e-57, +46, 26.65013225376606, 9.4952681597268829e-57, +46, 27.317572742700577, 2.3267585353541947e-57, +46, 27.317572750151157, 2.3267584721107382e-57, +46, 27.980030924081802, 6.0361758747634122e-58, +46, 27.980030931532383, 6.0361744186632288e-58, +46, 28.637481383979321, 1.6551114270590451e-58, +46, 28.637481391429901, 1.6551115121338961e-58, +46, 29.289894767105579, 4.7892134847685121e-59, +46, 29.28989477455616, 4.7892139632868144e-59, +46, 29.937237836420536, 1.4602051759997881e-59, +46, 29.937237843871117, 1.4602053759582893e-59, +46, 30.579473488032818, 4.68423576142464e-60, +46, 30.579473495483398, 4.6842348560181774e-60, +46, 31.216560810804367, 1.5787698767498073e-60, +46, 31.216560818254948, 1.5787694868993428e-60, +46, 31.848455116152763, 5.5827601398471846e-61, +46, 31.848455123603344, 5.5827605505046904e-61, +46, 32.475107997655869, 2.0684054277531821e-61, +46, 32.475108005106449, 2.0684050017914515e-61, +46, 33.096467457711697, 8.0184979475855917e-62, +46, 33.096467465162277, 8.0184996083569093e-62, +46, 33.712477974593639, 3.2481838404050001e-62, +46, 33.71247798204422, 3.2481845661858734e-62, +46, 34.323080711066723, 1.3730902387821525e-62, +46, 34.323080718517303, 1.3730905116669834e-62, +46, 34.928213715553284, 6.0490505093449614e-63, +46, 34.928213723003864, 6.0490502061549865e-63, +46, 35.527812235057354, 2.7738302273726239e-63, +46, 35.527812242507935, 2.7738300120352881e-63, +46, 36.121809102594852, 1.3219315330205259e-63, +46, 36.121809110045433, 1.3219315495101077e-63, +46, 36.710135266184807, 6.5381416094508987e-64, +46, 36.710135273635387, 6.5381395439195238e-64, +46, 37.29272049665451, 3.3511256183575924e-64, +46, 37.292720504105091, 3.3511253777416731e-64, +46, 37.869494251906872, 1.7782224670780664e-64, +46, 37.869494259357452, 1.7782230075236345e-64, +46, 38.440386839210987, 9.7485951877403594e-65, +46, 38.440386846661568, 9.7485987533710605e-65, +46, 39.005330882966518, 5.5118745257229395e-65, +46, 39.005330890417099, 5.5118758087036987e-65, +46, 39.564263164997101, 3.2086062422653907e-65, +46, 39.564263172447681, 3.2086059318791368e-65, +46, 40.117126934230328, 1.9195876578735422e-65, +46, 40.117126941680908, 1.9195871483787689e-65, +46, 40.663874745368958, 1.1796387047474248e-65, +46, 40.663874752819538, 1.1796390835335743e-65, +46, 41.204471878707409, 7.4302744969961591e-66, +46, 41.20447188615799, 7.4302749906208339e-66, +46, 41.738900445401669, 4.7787386204187361e-66, +46, 41.738900452852249, 4.7787368414768313e-66, +46, 42.267164044082165, 3.1309961982361379e-66, +46, 42.267164051532745, 3.1309970241249755e-66, +46, 42.789292871952057, 2.0848199024819712e-66, +46, 42.789292879402637, 2.0848208718454793e-66, +46, 43.305349059402943, 1.4072806979517762e-66, +46, 43.305349066853523, 1.4072808312475605e-66, +46, 43.815431639552116, 9.6052084550853495e-67, +46, 43.815431647002697, 9.6052117675199433e-67, +46, 44.319680452346802, 6.6113571969505894e-67, +46, 44.319680459797382, 6.6113606493408914e-67, +46, 44.818278186023235, 4.6166478078491933e-67, +46, 44.818278193473816, 4.6166471165314981e-67, +46, 45.311449721455574, 3.2739994282155191e-67, +46, 45.311449728906155, 3.2740001617951049e-67, +46, 45.799458242952824, 2.3237282013187023e-67, +46, 45.799458250403404, 2.3237271415390931e-67, +46, 46.282598368823528, 1.6469678742677118e-67, +46, 46.282598376274109, 1.6469671711065112e-67, +46, 46.761186890304089, 1.1632539359263231e-67, +46, 46.761186897754669, 1.1632546267503127e-67, +47, 0.80728960782289505, 4.168696487285219e-09, +47, 0.80728961527347565, 4.1686802748840336e-09, +47, 1.6803020089864731, 2.5862826437989554e-12, +47, 1.6803020164370537, 2.5862783742309297e-12, +47, 2.5419385433197021, 3.5589110032244365e-15, +47, 2.5419385507702827, 3.5589055350312847e-15, +47, 3.3936193436384201, 8.6937819098974955e-18, +47, 3.3936193510890007, 8.693773453710869e-18, +47, 4.236338347196579, 3.3334879834427222e-20, +47, 4.2363383546471596, 3.3334862351113778e-20, +47, 5.0708212777972221, 1.8539122147624523e-22, +47, 5.0708212852478027, 1.8539106465989753e-22, +47, 5.8976223096251488, 1.4151117759288016e-24, +47, 5.8976223170757294, 1.4151112842385029e-24, +47, 6.7171796038746834, 1.4231354913857727e-26, +47, 6.717179611325264, 1.4231349092066792e-26, +47, 7.5298490300774574, 1.8270991916084673e-28, +47, 7.529849037528038, 1.8270981509844472e-28, +47, 8.3359256163239479, 2.9204552900337321e-30, +47, 8.3359256237745285, 2.9204539068875798e-30, +47, 9.135657899081707, 5.6943540186214883e-32, +47, 9.1356579065322876, 5.694351434585495e-32, +47, 9.9292579293251038, 1.3316209970119361e-33, +47, 9.9292579367756844, 1.3316206287916541e-33, +47, 10.716908417642117, 3.681688466369277e-35, +47, 10.716908425092697, 3.6816872878015352e-35, +47, 11.498768046498299, 1.1888624622058115e-36, +47, 11.498768053948879, 1.1888620779052879e-36, +47, 12.274975448846817, 4.4364967703657409e-38, +47, 12.274975456297398, 4.4364963392181388e-38, +47, 13.045652270317078, 1.8956597245535588e-39, +47, 13.045652277767658, 1.895659468029324e-39, +47, 13.810905605554581, 9.1993530960854184e-41, +47, 13.810905613005161, 9.1993516327132913e-41, +47, 14.570829890668392, 5.0337694936051544e-42, +47, 14.570829898118973, 5.0337685733871596e-42, +47, 15.325508452951908, 3.0857782210815548e-43, +47, 15.325508460402489, 3.0857781885111563e-43, +47, 16.075014747679234, 2.1069353065285192e-44, +47, 16.075014755129814, 2.1069351219798955e-44, +47, 16.819413416087627, 1.5939494446404127e-45, +47, 16.819413423538208, 1.5939494724979777e-45, +47, 17.558761104941368, 1.3297370293876914e-46, +47, 17.558761112391949, 1.3297368751262161e-46, +47, 18.293107204139233, 1.2179710847308252e-47, +47, 18.293107211589813, 1.2179707147570524e-47, +47, 19.022494435310364, 1.2199964409560206e-48, +47, 19.022494442760944, 1.2199963161526724e-48, +47, 19.746959328651428, 1.3314974725625693e-49, +47, 19.746959336102009, 1.3314971821520744e-49, +47, 20.466532692313194, 1.5780264769522475e-50, +47, 20.466532699763775, 1.5780266017287087e-50, +47, 21.181239917874336, 2.0245178949773632e-51, +47, 21.181239925324917, 2.0245176315944763e-51, +47, 21.891101337969303, 2.8034948326469036e-52, +47, 21.891101345419884, 2.8034939685782499e-52, +47, 22.596132457256317, 4.1790008688926555e-53, +47, 22.596132464706898, 4.1790007819449501e-53, +47, 23.29634415358305, 6.688690844654884e-54, +47, 23.29634416103363, 6.6886903967838107e-54, +47, 23.99174290150404, 1.1467692853330373e-54, +47, 23.99174290895462, 1.146769186365129e-54, +47, 24.682330906391144, 2.1014056175149362e-55, +47, 24.682330913841724, 2.101405889230169e-55, +47, 25.368106223642826, 4.1070651602071193e-56, +47, 25.368106231093407, 4.1070645819933285e-56, +47, 26.04906290769577, 8.5443697879268007e-57, +47, 26.049062915146351, 8.5443710805019463e-57, +47, 26.725191041827202, 1.8886008815516421e-57, +47, 26.725191049277782, 1.8886004404999289e-57, +47, 27.396476879715919, 4.4272816933018068e-58, +47, 27.3964768871665, 4.4272808898189293e-58, +47, 28.062902852892876, 1.0988364859194886e-58, +47, 28.062902860343456, 1.0988366253920036e-58, +47, 28.724447630345821, 2.8828564728611722e-59, +47, 28.724447637796402, 2.8828560006070042e-59, +47, 29.381086193025112, 7.9823493818795601e-60, +47, 29.381086200475693, 7.9823486515529818e-60, +47, 30.032789826393127, 2.3291962093493194e-60, +47, 30.032789833843708, 2.3291961095189567e-60, +47, 30.679526172578335, 7.1518997842789854e-61, +47, 30.679526180028915, 7.1518973239508013e-61, +47, 31.321259275078773, 2.307641249370635e-61, +47, 31.321259282529354, 2.3076405172220076e-61, +47, 31.957949593663216, 7.8136659014415755e-62, +47, 31.957949601113796, 7.8136652248427256e-62, +47, 32.58955405652523, 2.7726990903841993e-62, +47, 32.589554063975811, 2.7726984868935579e-62, +47, 33.216026142239571, 1.0297785058851998e-62, +47, 33.216026149690151, 1.0297785317772547e-62, +47, 33.837315931916237, 3.9977694884441333e-63, +47, 33.837315939366817, 3.9977697411365166e-63, +47, 34.453370243310928, 1.6201996067502547e-63, +47, 34.453370250761509, 1.6201992966533348e-63, +47, 35.064132787287235, 6.8460691000177028e-64, +47, 35.064132794737816, 6.8460695120204543e-64, +47, 35.669544346630573, 3.0121713471962354e-64, +47, 35.669544354081154, 3.0121713531964038e-64, +47, 36.269543081521988, 1.3784224526611186e-64, +47, 36.269543088972569, 1.3784225213845312e-64, +47, 36.864064872264862, 6.551031389687536e-65, +47, 36.864064879715443, 6.5510309622836689e-65, +47, 37.453043811023235, 3.2290009692268078e-65, +47, 37.453043818473816, 3.2290017963920392e-65, +47, 38.036412797868252, 1.6483961550238261e-65, +47, 38.036412805318832, 1.6483964581988733e-65, +47, 38.614104360342026, 8.7068430193326876e-66, +47, 38.614104367792606, 8.7068402136754839e-66, +47, 39.186051674187183, 4.7496069713042888e-66, +47, 39.186051681637764, 4.7496053262899038e-66, +47, 39.752189837396145, 2.6711638237868345e-66, +47, 39.752189844846725, 2.6711631630388347e-66, +47, 40.312457516789436, 1.5462743542785204e-66, +47, 40.312457524240017, 1.5462749942360846e-66, +47, 40.86679895222187, 9.197576438140017e-67, +47, 40.866798959672451, 9.1975795377859577e-67, +47, 41.415166474878788, 5.6155851602094119e-67, +47, 41.415166482329369, 5.6155838713502694e-67, +47, 41.957523517310619, 3.5168645107743576e-67, +47, 41.9575235247612, 3.5168655127769924e-67, +47, 42.493848152458668, 2.2493284118817205e-67, +47, 42.493848159909248, 2.2493291438227212e-67, +47, 43.024137258529663, 1.4660650820917181e-67, +47, 43.024137265980244, 1.4660656316867027e-67, +47, 43.548411078751087, 9.7156719582995046e-68, +47, 43.548411086201668, 9.7156694474500461e-68, +47, 44.066718079149723, 6.5310259797325952e-68, +47, 44.066718086600304, 6.5310260879476081e-68, +47, 44.579139620065689, 4.442438020547419e-68, +47, 44.57913962751627, 4.4424398622724323e-68, +47, 45.085793986916542, 3.0499884991862987e-68, +47, 45.085793994367123, 3.0499874345652321e-68, +47, 45.586839035153389, 2.1083600642969428e-68, +47, 45.58683904260397, 2.1083609447567937e-68, +47, 46.082472607493401, 1.4938147144274907e-68, +47, 46.082472614943981, 1.4938153354270103e-68, +47, 46.572930358350277, 1.0602813294127947e-68, +47, 46.572930365800858, 1.0602819311490823e-68, +47, 47.058480642735958, 7.5239566886279539e-69, +47, 47.058480650186539, 7.5239599111949498e-69, +47, 47.539416998624802, 5.3260856872391961e-69, +47, 47.539417006075382, 5.3260856592438819e-69, +48, 0.8081108033657074, 3.790537216779154e-09, +48, 0.80811081081628799, 3.7905242694972794e-09, +48, 1.6817938983440399, 2.2504531682948115e-12, +48, 1.6817939057946205, 2.2504483820670804e-12, +48, 2.5442163795232773, 2.9637275510465843e-15, +48, 2.5442163869738579, 2.9637227676420457e-15, +48, 3.3967880085110664, 6.9290264628280876e-18, +48, 3.396788015961647, 6.9290183337540871e-18, +48, 4.2404954805970192, 2.5428118362391363e-20, +48, 4.2404954880475998, 2.5428091511397717e-20, +48, 5.0760592594742775, 1.3535154982948461e-22, +48, 5.0760592669248581, 1.3535145215948875e-22, +48, 5.9040295109152794, 9.8885231815640295e-25, +48, 5.90402951836586, 9.8885168237279911e-25, +48, 6.7248413637280464, 9.518302995514812e-27, +48, 6.724841371178627, 9.5183002220780383e-27, +48, 7.5388482883572578, 1.1696457368664985e-28, +48, 7.5388482958078384, 1.169645374012626e-28, +48, 8.346343457698822, 1.7894833131442889e-30, +48, 8.3463434651494026, 1.7894824081088118e-30, +48, 9.1475740000605583, 3.3397293242857729e-32, +48, 9.1475740075111389, 3.339728176140613e-32, +48, 9.9427508860826492, 7.4755270996096026e-34, +48, 9.9427508935332298, 7.4755256245678417e-34, +48, 10.732056066393852, 1.9783655047619916e-35, +48, 10.732056073844433, 1.9783652198251722e-35, +48, 11.51564771682024, 6.1149507579983915e-37, +48, 11.515647724270821, 6.1149494622707338e-37, +48, 12.293664202094078, 2.1842708433101863e-38, +48, 12.293664209544659, 2.1842700354917262e-38, +48, 13.066227130591869, 8.9337538377953074e-40, +48, 13.06622713804245, 8.9337502859897068e-40, +48, 13.833443738520145, 4.149924620485562e-41, +48, 13.833443745970726, 4.1499237221656357e-41, +48, 14.595408782362938, 2.1736394745132589e-42, +48, 14.595408789813519, 2.173638813907354e-42, +48, 15.352206096053123, 1.2754745467294774e-43, +48, 15.352206103503704, 1.2754741693102798e-43, +48, 16.103909812867641, 8.3362836739294546e-45, +48, 16.103909820318222, 8.3362820544674689e-45, +48, 16.850585393607616, 6.0368656344880979e-46, +48, 16.850585401058197, 6.0368647910276049e-46, +48, 17.592290475964546, 4.8208082646747087e-47, +48, 17.592290483415127, 4.8208065336171195e-47, +48, 18.32907559722662, 4.2267802866741478e-48, +48, 18.3290756046772, 4.2267788247523572e-48, +48, 19.060984767973423, 4.0527677000262975e-49, +48, 19.060984775424004, 4.0527678696098182e-49, +48, 19.788055963814259, 4.2340523931993972e-50, +48, 19.788055971264839, 4.2340524276091812e-50, +48, 20.510321587324142, 4.8034783455880191e-51, +48, 20.510321594774723, 4.8034780348731884e-51, +48, 21.227808803319931, 5.899186088148869e-52, +48, 21.227808810770512, 5.8991860762611689e-52, +48, 21.940539844334126, 7.8199420923371399e-53, +48, 21.940539851784706, 7.8199427514005375e-53, +48, 22.648532271385193, 1.1158743726808565e-53, +48, 22.648532278835773, 1.1158741101131104e-53, +48, 23.351799219846725, 1.7097382876171394e-54, +48, 23.351799227297306, 1.7097378990809491e-54, +48, 24.050349555909634, 2.8062000362026087e-55, +48, 24.050349563360214, 2.8062001977088843e-55, +48, 24.744188040494919, 4.9228561141945363e-56, +48, 24.744188047945499, 4.9228560221850344e-56, +48, 25.433315485715866, 9.2112000380037501e-57, +48, 25.433315493166447, 9.2111973817050768e-57, +48, 26.117728859186172, 1.8346687861945116e-57, +48, 26.117728866636753, 1.8346682350681618e-57, +48, 26.797421365976334, 3.8826606576023508e-58, +48, 26.797421373426914, 3.8826600315338496e-58, +48, 27.47238253057003, 8.7148703279250707e-59, +48, 27.472382538020611, 8.7148674108098657e-59, +48, 28.142598286271095, 2.0711829791398647e-59, +48, 28.142598293721676, 2.0711832322860257e-59, +48, 28.808050975203514, 5.203584010105859e-60, +48, 28.808050982654095, 5.2035828616190226e-60, +48, 29.468719460070133, 1.3798854862844653e-60, +48, 29.468719467520714, 1.3798850951568444e-60, +48, 30.124579109251499, 3.8565307240880389e-61, +48, 30.12457911670208, 3.8565299743759719e-61, +48, 30.775601848959923, 1.134342736876812e-61, +48, 30.775601856410503, 1.1343429076941469e-61, +48, 31.42175617814064, 3.5066060548219019e-62, +48, 31.421756185591221, 3.5066056252289294e-62, +48, 32.063007235527039, 1.1377415805787006e-62, +48, 32.063007242977619, 1.1377415420726448e-62, +48, 32.699316792190075, 3.8694437991207317e-63, +48, 32.699316799640656, 3.8694430678757391e-63, +48, 33.330643333494663, 1.3776788233453704e-63, +48, 33.330643340945244, 1.3776791661638305e-63, +48, 33.956942074000835, 5.1285952783952753e-64, +48, 33.956942081451416, 5.1285947602355625e-64, +48, 34.578165091574192, 1.9937127927134763e-64, +48, 34.578165099024773, 1.9937126593845751e-64, +48, 35.194261386990547, 8.0836531292607215e-65, +48, 35.194261394441128, 8.0836543290621667e-65, +48, 35.805177040398121, 3.4143034915050112e-65, +48, 35.805177047848701, 3.4143040521491458e-65, +48, 36.410855405032635, 1.5004193222265229e-65, +48, 36.410855412483215, 1.5004189889736636e-65, +48, 37.011237367987633, 6.8526723104762059e-66, +48, 37.011237375438213, 6.8526715926507402e-66, +49, 32.804697265625, 1.43398975614025e-77, +49, 32.80474609375, 1.44673437055229e-77, +49, 33.440634765625, 4.27570575602756e-78, +49, 33.44068359375, 4.31374583006685e-78, +49, 34.071689453125, 1.3311629562209e-78, +49, 34.07173828125, 1.34302740537616e-78, +49, 34.6978125, 4.3180939436597e-79, +49, 34.697861328125, 4.35671988075901e-79, +49, 35.31900390625, 1.47025173244693e-79, +49, 35.319052734375, 1.48336146723368e-79, +49, 35.9351171875, 5.15604524622028e-80, +49, 35.935166015625, 5.20239853250623e-80, +49, 36.546201171875, 1.89501379810394e-80, +49, 36.54625, 1.9120635932297e-80, +49, 37.152109375, 7.16858816674083e-81, +49, 37.152158203125, 7.23377831202289e-81, +49, 37.752890625, 2.84316453204977e-81, +49, 37.752939453125, 2.86903747838692e-81, +49, 38.3483984375, 1.16185980624431e-81, +49, 38.348447265625, 1.17251002885751e-81, +49, 38.938583984375, 4.89658368061457e-82, +49, 38.9386328125, 4.94200005973042e-82, +49, 39.5233984375, 2.13065629695396e-82, +49, 39.523447265625, 2.15069572328143e-82, +49, 40.102841796875, 9.67604255181201e-83, +49, 40.102890625, 9.76740702977543e-83, +49, 40.676767578125, 4.50630247183498e-83, +49, 40.67681640625, 4.54930080744076e-83, +49, 41.245126953125, 2.15387681720274e-83, +49, 41.24517578125, 2.17473706057203e-83, +49, 41.80787109375, 1.05682121783075e-83, +49, 41.807919921875, 1.06723874854161e-83, +49, 42.365, 5.3732505406968e-84, +49, 42.365048828125, 5.42671775522331e-84, +49, 42.916416015625, 2.79825365457182e-84, +49, 42.91646484375, 2.82641567518989e-84, +49, 43.4620703125, 1.48702015592533e-84, +49, 43.462119140625, 1.50221776839907e-84, +49, 44.0019140625, 8.01177208266458e-85, +49, 44.001962890625, 8.09565323702789e-85, +49, 44.53599609375, 4.42566611189109e-85, +49, 44.536044921875, 4.47291966331024e-85, +49, 45.06431640625, 2.49957129718041e-85, +49, 45.064365234375, 2.52668601869568e-85, +49, 45.586875, 1.43196123451618e-85, +49, 45.586923828125, 1.4477759848853e-85, +49, 46.10376953125, 8.38746806134962e-86, +49, 46.103818359375, 8.48100243483236e-86, +49, 46.615, 4.91772041740201e-86, +49, 46.615048828125, 4.97369333258043e-86, +49, 47.120712890625, 2.8986790595583e-86, +49, 47.12076171875, 2.93248475871069e-86, +49, 47.621103515625, 1.73183181437907e-86, +49, 47.62115234375, 1.75238561661062e-86, +49, 48.116318359375, 1.03658031298704e-86, +49, 48.1163671875, 1.04913081745512e-86, +49, 48.6066015625, 6.24079697368347e-87, +49, 48.606650390625, 6.31757720373193e-87, +50, 33.54638671875, 1.92761599350307e-79, +50, 33.546435546875, 1.94516650364829e-79, +50, 34.181982421875, 5.76192865620046e-80, +50, 34.18203125, 5.81436002400983e-80, +50, 34.81279296875, 1.79764857133798e-80, +50, 34.812841796875, 1.81400022919546e-80, +50, 35.438720703125, 5.78653632499813e-81, +50, 35.43876953125, 5.83972710207297e-81, +50, 36.05986328125, 1.97160801805539e-81, +50, 36.059912109375, 1.98962723354967e-81, +50, 36.676025390625, 6.90862452044191e-82, +50, 36.67607421875, 6.97216511712785e-82, +50, 37.28720703125, 2.51020639219632e-82, +50, 37.287255859375, 2.533501052945e-82, +50, 37.893408203125, 9.54172211017555e-83, +50, 37.89345703125, 9.63040270153392e-83, +50, 38.494482421875, 3.7244684010854e-83, +50, 38.49453125, 3.75949927313683e-83, +50, 39.090478515625, 1.52160071659105e-83, +50, 39.09052734375, 1.53593965559733e-83, +50, 39.68125, 6.38933786856091e-84, +50, 39.681298828125, 6.45010684683321e-84, +50, 40.266748046875, 2.75949080957442e-84, +50, 40.266796875, 2.78612547118161e-84, +50, 40.84697265625, 1.23878873498316e-84, +50, 40.847021484375, 1.25084568494597e-84, +50, 41.421826171875, 5.73021424860067e-85, +50, 41.421875, 5.78652397826679e-85, +50, 41.991259765625, 2.7328651665849e-85, +50, 41.99130859375, 2.75996267833758e-85, +50, 42.55517578125, 1.3306120670112e-85, +50, 42.555224609375, 1.34403199525941e-85, +50, 43.11357421875, 6.67538976472161e-86, +50, 43.113623046875, 6.74368293994306e-86, +50, 43.66640625, 3.44457915579056e-86, +50, 43.666455078125, 3.48023818015529e-86, +50, 44.213623046875, 1.82191303634907e-86, +50, 44.213671875, 1.84098742019443e-86, +50, 44.75517578125, 9.8204850440831e-87, +50, 44.755224609375, 9.9248385898419e-87, +50, 45.291015625, 5.34608946266382e-87, +50, 45.291064453125, 5.40437863458585e-87, +50, 45.821240234375, 2.99827983616452e-87, +50, 45.8212890625, 3.03145075570816e-87, +50, 46.34580078125, 1.70330388065361e-87, +50, 46.345849609375, 1.7224993598544e-87, +50, 46.864794921875, 9.90800075053591e-88, +50, 46.86484375, 1.00207004805813e-87, +50, 47.378173828125, 5.7288229698866e-88, +50, 47.37822265625, 5.79582150586751e-88, +50, 47.886181640625, 3.39976963258209e-88, +50, 47.88623046875, 3.43999283382834e-88, +50, 48.388818359375, 2.00196389521248e-88, +50, 48.3888671875, 2.02630021564974e-88, +50, 48.886376953125, 1.20465247273191e-88, +50, 48.88642578125, 1.21945216999773e-88, +50, 49.378955078125, 7.21301501171278e-89, +50, 49.37900390625, 7.30328914193871e-89, +50, 49.866796875, 4.30834039532944e-89, +50, 49.866845703125, 4.36344856692381e-89, +51, 34.28802734375, 2.50653782215963e-81, +51, 34.288076171875, 2.53000371457217e-81, +51, 34.92328125, 7.49158638633263e-82, +51, 34.923330078125, 7.5617476436076e-82, +51, 35.55384765625, 2.33786811783389e-82, +51, 35.553896484375, 2.35974650122535e-82, +51, 36.179677734375, 7.59715649735025e-83, +51, 36.1797265625, 7.66823998247397e-83, +51, 36.800673828125, 2.54120219840682e-83, +51, 36.80072265625, 2.5652464992018e-83, +51, 37.416884765625, 8.90060057210517e-84, +51, 37.41693359375, 8.98516095098549e-84, +51, 38.02826171875, 3.26067023053424e-84, +51, 38.028310546875, 3.29155983535777e-84, +51, 38.634658203125, 1.22494879115424e-84, +51, 38.63470703125, 1.23666166304672e-84, +51, 39.23607421875, 4.76183281948702e-85, +51, 39.236123046875, 4.80788045863205e-85, +51, 39.832509765625, 1.93410326826023e-85, +51, 39.83255859375, 1.95285023241101e-85, +51, 40.423818359375, 8.05264364304082e-86, +51, 40.4238671875, 8.13162262140464e-86, +51, 41.01, 3.47176148694309e-86, +51, 41.010048828125, 3.50614975628603e-86, +51, 41.591005859375, 1.55093045558687e-86, +51, 41.5910546875, 1.56638804232732e-86, +51, 42.16673828125, 7.11162716693627e-87, +51, 42.166787109375, 7.18328462123865e-87, +51, 42.7371484375, 3.34775725369505e-87, +51, 42.737197265625, 3.3819741026035e-87, +51, 43.302236328125, 1.63427281479688e-87, +51, 43.30228515625, 1.65107897871875e-87, +51, 43.86185546875, 8.09778432115049e-88, +51, 43.861904296875, 8.1826011369978e-88, +51, 44.4160546875, 4.14978056128476e-88, +51, 44.416103515625, 4.19369025316849e-88, +51, 44.964736328125, 2.16908484161885e-88, +51, 44.96478515625, 2.19237214768002e-88, +51, 45.507900390625, 1.16244501700139e-88, +51, 45.50794921875, 1.17507586155075e-88, +51, 46.045498046875, 6.33568823869884e-89, +51, 46.045546875, 6.4056389506585e-89, +51, 46.577529296875, 3.50966350105409e-89, +51, 46.577578125, 3.54914608970848e-89, +51, 47.103994140625, 1.9666300290808e-89, +51, 47.10404296875, 1.98929989871267e-89, +51, 47.624990234375, 1.12975553299459e-89, +51, 47.6250390625, 1.14296776906837e-89, +51, 48.140517578125, 6.55256898902797e-90, +51, 48.14056640625, 6.630573396527e-90, +51, 48.650673828125, 3.84161435604585e-90, +51, 48.65072265625, 3.88816278976081e-90, +51, 49.155556640625, 2.26271437569233e-90, +51, 49.15560546875, 2.29072792758847e-90, +51, 49.655361328125, 1.35342362614108e-90, +51, 49.65541015625, 1.37038547515428e-90, +51, 50.150185546875, 8.04288108914844e-91, +51, 50.150234375, 8.14599579489655e-91, +51, 50.640322265625, 4.85018565373833e-91, +51, 50.64037109375, 4.91297519323409e-91, +52, 34.3901171875, 1.09784132477666e-82, +52, 34.390166015625, 1.10845736512505e-82, +52, 35.029619140625, 3.14965843034692e-83, +52, 35.02966796875, 3.18011008403191e-83, +52, 35.664580078125, 9.47858460950038e-84, +52, 35.66462890625, 9.56968525920582e-84, +52, 36.29490234375, 2.95312719534554e-84, +52, 36.294951171875, 2.98153078194748e-84, +52, 36.9205859375, 9.58907405270613e-85, +52, 36.920634765625, 9.68126325492615e-85, +52, 37.541533203125, 3.20598766092008e-85, +52, 37.54158203125, 3.23711321193289e-85, +52, 38.15779296875, 1.1229532977843e-85, +52, 38.157841796875, 1.13387086000462e-85, +52, 38.769267578125, 4.07481357929281e-86, +52, 38.76931640625, 4.11456729015147e-86, +52, 39.375908203125, 1.53004878535561e-86, +52, 39.37595703125, 1.54506157346258e-86, +52, 39.977666015625, 5.94046664964127e-87, +52, 39.97771484375, 5.99920997458957e-87, +52, 40.5744921875, 2.38377058782452e-87, +52, 40.574541015625, 2.40756323337164e-87, +52, 41.166337890625, 9.88492129468606e-88, +52, 41.16638671875, 9.98457131300606e-88, +52, 41.753154296875, 4.23624932947817e-88, +52, 41.753203125, 4.27936286666186e-88, +52, 42.334892578125, 1.87664263717547e-88, +52, 42.33494140625, 1.89589075628466e-88, +52, 42.91150390625, 8.59533063061209e-89, +52, 42.911552734375, 8.6839076793046e-89, +52, 43.482890625, 4.02833193451732e-89, +52, 43.482939453125, 4.07030503687417e-89, +52, 44.04900390625, 1.93062243793654e-89, +52, 44.049052734375, 1.9510780127415e-89, +52, 44.60984375, 9.55143090611608e-90, +52, 44.609892578125, 9.6538161099766e-90, +52, 45.1653125, 4.81625778814193e-90, +52, 45.165361328125, 4.86882655159775e-90, +52, 45.715458984375, 2.52110578486338e-90, +52, 45.7155078125, 2.54874785641837e-90, +52, 46.26013671875, 1.33336774124782e-90, +52, 46.260185546875, 1.34823517438449e-90, +52, 46.79939453125, 7.22810225870508e-91, +52, 46.799443359375, 7.30975111869956e-91, +52, 47.33318359375, 3.97344561651893e-91, +52, 47.333232421875, 4.01915570075938e-91, +52, 47.86150390625, 2.20743711754887e-91, +52, 47.861552734375, 2.23347698762707e-91, +52, 48.384453125, 1.25905367991677e-91, +52, 48.384501953125, 1.27411715811031e-91, +52, 48.90203125, 7.27905637066785e-92, +52, 48.902080078125, 7.36737320296161e-92, +52, 49.414287109375, 4.23381379773091e-92, +52, 49.4143359375, 4.28618644566405e-92, +52, 49.9213671875, 2.50298615147254e-92, +52, 49.921416015625, 2.53432810782328e-92, +52, 50.4233203125, 1.47126510667252e-92, +52, 50.423369140625, 1.49015523321499e-92, +52, 50.920390625, 8.77981976716807e-93, +52, 50.920439453125, 8.89421391691748e-93, +52, 51.41267578125, 5.18853729438254e-93, +52, 51.4127734375, 5.32746953609488e-93, +52, 51.90046875, 3.10020589622689e-93, +52, 51.90056640625, 3.18462954145289e-93, +53, 35.132099609375, 1.34165815167586e-84, +53, 35.1321484375, 1.35500182297823e-84, +53, 35.7712109375, 3.8586346438587e-85, +53, 35.771259765625, 3.89696659256537e-85, +53, 36.405830078125, 1.15515485184e-85, +53, 36.40587890625, 1.16663065451713e-85, +53, 37.03595703125, 3.62188787444457e-86, +53, 37.036005859375, 3.65765415366427e-86, +53, 37.6614453125, 1.16222508687862e-86, +53, 37.661494140625, 1.17382378602205e-86, +53, 38.282392578125, 3.9213181641527e-87, +53, 38.28244140625, 3.96039919460395e-87, +53, 38.898701171875, 1.37417257661721e-87, +53, 38.89875, 1.38784484660129e-87, +53, 39.5102734375, 4.94269999592506e-88, +53, 39.510322265625, 4.99232702818206e-88, +53, 40.117109375, 1.84017054708022e-88, +53, 40.117158203125, 1.85883994034502e-88, +53, 40.719208984375, 7.15588091788769e-89, +53, 40.7192578125, 7.22859337586009e-89, +53, 41.316474609375, 2.87513573445484e-89, +53, 41.3165234375, 2.90443251849943e-89, +53, 41.90880859375, 1.18074666272332e-89, +53, 41.908857421875, 1.19294813450042e-89, +53, 42.496259765625, 5.05747920130745e-90, +53, 42.49630859375, 5.10993883553687e-90, +53, 43.078681640625, 2.21264357218252e-90, +53, 43.07873046875, 2.23591087175254e-90, +53, 43.65607421875, 9.98793944641443e-91, +53, 43.656123046875, 1.00942684217088e-90, +53, 44.228388671875, 4.65040411340808e-91, +53, 44.2284375, 4.7004152251227e-91, +53, 44.795576171875, 2.23187504561532e-91, +53, 44.795625, 2.25605716326726e-91, +53, 45.3575390625, 1.09071767039123e-91, +53, 45.357587890625, 1.10272568727892e-91, +53, 45.91427734375, 5.47462949180705e-92, +53, 45.914326171875, 5.53577914514396e-92, +53, 46.4657421875, 2.81267854173599e-92, +53, 46.465791015625, 2.84457112046934e-92, +53, 47.01193359375, 1.48845783243062e-92, +53, 47.011982421875, 1.50546780296832e-92, +53, 47.55275390625, 7.96299241886377e-93, +53, 47.552802734375, 8.05564452331045e-93, +53, 48.088251953125, 4.36254557224574e-93, +53, 48.08830078125, 4.41399477393221e-93, +53, 48.61837890625, 2.41436230087065e-93, +53, 48.618427734375, 2.44344138971554e-93, +53, 49.143232421875, 1.3742563864423e-93, +53, 49.14328125, 1.39095171064196e-93, +53, 49.662763671875, 7.8627249720243e-94, +53, 49.6628125, 7.95992783735172e-94, +53, 50.1770703125, 4.55653379867663e-94, +53, 50.177119140625, 4.61380444528666e-94, +53, 50.686201171875, 2.64507670539115e-94, +53, 50.68625, 2.6791564695207e-94, +53, 51.1903515625, 1.56964252641228e-94, +53, 51.190400390625, 1.59007794504541e-94, +53, 51.6895703125, 9.2823621015156e-95, +53, 51.68966796875, 9.5288381887029e-95, +53, 52.18400390625, 5.4283757570851e-95, +53, 52.1841015625, 5.5775793180482e-95, +53, 52.6739453125, 3.22377149580101e-95, +53, 52.67404296875, 3.31422857776726e-95, +54, 35.87408203125, 1.60299124464084e-86, +54, 35.874130859375, 1.61925498333934e-86, +54, 36.512802734375, 4.60744049715477e-87, +54, 36.5128515625, 4.6542262775045e-87, +54, 37.14712890625, 1.38230307333573e-87, +54, 37.147177734375, 1.3963165242666e-87, +54, 37.776962890625, 4.2676811431326e-88, +54, 37.77701171875, 4.31135557415735e-88, +54, 38.402353515625, 1.37886617731339e-88, +54, 38.40240234375, 1.39301204526773e-88, +54, 39.023251953125, 4.64806876395431e-89, +54, 39.02330078125, 4.69564494367985e-89, +54, 39.639560546875, 1.61376384913413e-89, +54, 39.639609375, 1.63036800302231e-89, +54, 40.251279296875, 5.81713197366461e-90, +54, 40.251328125, 5.87720283929007e-90, +54, 40.858359375, 2.17315978880267e-90, +54, 40.858408203125, 2.19566884825944e-90, +54, 41.460703125, 8.31413664866219e-91, +54, 41.460751953125, 8.40143100626546e-91, +54, 42.058359375, 3.32234094377706e-91, +54, 42.058408203125, 3.35733728990472e-91, +54, 42.65123046875, 1.37108630576255e-91, +54, 42.651279296875, 1.38557871529173e-91, +54, 43.23921875, 5.77759110628069e-92, +54, 43.239267578125, 5.8395345444883e-92, +54, 43.822373046875, 2.53796499025021e-92, +54, 43.822421875, 2.56525705223881e-92, +54, 44.400546875, 1.13685971567258e-92, +54, 44.400595703125, 1.14924635408225e-92, +54, 44.973740234375, 5.24494903201998e-93, +54, 44.9737890625, 5.30278922556907e-93, +54, 45.541904296875, 2.48974278621437e-93, +54, 45.541953125, 2.51750108068007e-93, +54, 46.104990234375, 1.21416817580495e-93, +54, 46.1050390625, 1.22784384566186e-93, +54, 46.66294921875, 6.06863156354183e-94, +54, 46.662998046875, 6.13771586650707e-94, +54, 47.215732421875, 3.09782695797381e-94, +54, 47.21578125, 3.13356585781024e-94, +54, 47.763291015625, 1.60666638154662e-94, +54, 47.76333984375, 1.62557509885327e-94, +54, 48.305673828125, 8.60651173329294e-95, +54, 48.30572265625, 8.70866176467966e-95, +54, 48.842783203125, 4.66138641992004e-95, +54, 48.84283203125, 4.71765875807128e-95, +54, 49.37466796875, 2.58125106144261e-95, +54, 49.374716796875, 2.61280647106825e-95, +54, 49.901279296875, 1.43706251427965e-95, +54, 49.901328125, 1.4550467561572e-95, +54, 50.42271484375, 8.17008391727145e-96, +54, 50.422763671875, 8.27405152155282e-96, +54, 50.9390234375, 4.73629466134273e-96, +54, 50.939072265625, 4.79714657796633e-96, +54, 51.45015625, 2.70637622493452e-96, +54, 51.45025390625, 2.77837012006172e-96, +54, 51.95640625, 1.60392443466118e-96, +54, 51.95650390625, 1.6468673251926e-96, +54, 52.4577734375, 9.52380966519104e-97, +54, 52.45787109375, 9.78162481883129e-97, +54, 52.95435546875, 5.57472185760653e-97, +54, 52.954453125, 5.73022000928701e-97, +54, 53.4464453125, 3.32141601130766e-97, +54, 53.44654296875, 3.41542726435434e-97, +54, 53.934140625, 1.95568174192375e-97, +54, 53.93423828125, 2.01256167035286e-97, +55, 36.615966796875, 1.8332541133448e-88, +55, 36.616015625, 1.85247560570567e-88, +55, 37.254345703125, 5.30481775801044e-89, +55, 37.25439453125, 5.36017474932385e-89, +55, 37.88837890625, 1.59132201617429e-89, +55, 37.888427734375, 1.60790995949161e-89, +55, 38.518017578125, 4.92735433868831e-90, +55, 38.51806640625, 4.97903083471312e-90, +55, 39.14326171875, 1.58522865714114e-90, +55, 39.143310546875, 1.60194883269875e-90, +55, 39.764111328125, 5.33698675182668e-91, +55, 39.76416015625, 5.39311857875617e-91, +55, 40.38046875, 1.85508041787031e-91, +55, 40.380517578125, 1.8746204836555e-91, +55, 40.99228515625, 6.63996228149307e-92, +55, 40.992333984375, 6.71043727342021e-92, +55, 41.599560546875, 2.46798186824746e-92, +55, 41.599609375, 2.49429084756772e-92, +55, 42.202197265625, 9.40692186686793e-93, +55, 42.20224609375, 9.50850937940109e-93, +55, 42.800244140625, 3.75106220500044e-93, +55, 42.80029296875, 3.79158825843364e-93, +55, 43.3935546875, 1.52947380015209e-93, +55, 43.393603515625, 1.54616717565206e-93, +55, 43.98212890625, 6.43906065579312e-94, +55, 43.982177734375, 6.50998764609593e-94, +55, 44.56591796875, 2.79632632865198e-94, +55, 44.565966796875, 2.82738157386603e-94, +55, 45.144873046875, 1.25150437492926e-94, +55, 45.144921875, 1.26550343381352e-94, +55, 45.7189453125, 5.76629149742495e-95, +55, 45.718994140625, 5.83119549719855e-95, +55, 46.288037109375, 2.70055229254301e-95, +55, 46.2880859375, 2.73147381215483e-95, +55, 46.852197265625, 1.31270463114748e-95, +55, 46.85224609375, 1.32782212771267e-95, +55, 47.411279296875, 6.45560417517413e-96, +55, 47.411328125, 6.53138347837362e-96, +55, 47.96533203125, 3.27538902561878e-96, +55, 47.965380859375, 3.31427965467404e-96, +55, 48.5142578125, 1.68599305405381e-96, +55, 48.514306640625, 1.70640462719072e-96, +55, 49.05810546875, 8.95772389297722e-97, +55, 49.058154296875, 9.06711241441999e-97, +55, 49.59677734375, 4.8089458433976e-97, +55, 49.596826171875, 4.86873031520792e-97, +55, 50.130322265625, 2.64138783197092e-97, +55, 50.13037109375, 2.67465396471993e-97, +55, 50.658740234375, 1.47989802765765e-97, +55, 50.6587890625, 1.49871358521579e-97, +55, 51.181982421875, 8.287936462558e-98, +55, 51.18203125, 8.39594586787481e-98, +55, 51.7001953125, 4.76307652889875e-98, +55, 51.70029296875, 4.88866793750702e-98, +55, 52.21337890625, 2.75947508065571e-98, +55, 52.2134765625, 2.83330856381719e-98, +55, 52.72158203125, 1.59307203690564e-98, +55, 52.7216796875, 1.63687980385948e-98, +55, 53.225, 9.37441146592157e-99, +55, 53.22509765625, 9.63618543580853e-99, +55, 53.72373046875, 5.56087800966994e-99, +55, 53.723828125, 5.71812073882941e-99, +55, 54.21787109375, 3.26344577772922e-99, +55, 54.21796875, 3.3582248315885e-99, +55, 54.70771484375, 1.95673422065812e-99, +55, 54.7078125, 2.01394065913309e-99, +56, 37.3578515625, 2.04647041348259e-90, +56, 37.357900390625, 2.06847980628938e-90, +56, 37.99583984375, 5.88243837411135e-91, +56, 37.995888671875, 5.94590494289821e-91, +56, 38.629580078125, 1.76021316827907e-91, +56, 38.62962890625, 1.77923863437215e-91, +56, 39.2590234375, 5.45779852011259e-92, +56, 39.259072265625, 5.51704239356607e-92, +56, 39.884169921875, 1.76524851588723e-92, +56, 39.88421875, 1.78439348136451e-92, +56, 40.504970703125, 5.93342330120247e-93, +56, 40.50501953125, 5.9975792008348e-93, +56, 41.121328125, 2.04345614663194e-93, +56, 41.121376953125, 2.06573687666038e-93, +56, 41.733291015625, 7.34765755919972e-94, +56, 41.73333984375, 7.42775943660008e-94, +56, 42.34076171875, 2.72161843366724e-94, +56, 42.340810546875, 2.75141110970169e-94, +56, 42.94369140625, 1.03613177248368e-94, +56, 42.943740234375, 1.04758637844824e-94, +56, 43.542080078125, 4.09126499345346e-95, +56, 43.54212890625, 4.13674598350119e-95, +56, 44.135830078125, 1.65424896423927e-95, +56, 44.13587890625, 1.67288546036148e-95, +56, 44.724990234375, 6.99446261996147e-96, +56, 44.7250390625, 7.07318147969286e-96, +56, 45.3094140625, 3.01976769844332e-96, +56, 45.309462890625, 3.05402248905396e-96, +56, 45.889052734375, 1.32918182143927e-96, +56, 45.8891015625, 1.34452414236527e-96, +56, 46.463955078125, 6.09433185040725e-97, +56, 46.46400390625, 6.16497223474698e-97, +56, 47.033974609375, 2.83946834327271e-97, +56, 47.0340234375, 2.87288014917526e-97, +56, 47.599111328125, 1.35701697542241e-97, +56, 47.59916015625, 1.37323222143338e-97, +56, 48.159365234375, 6.71405638326024e-98, +56, 48.1594140625, 6.79470565448062e-98, +56, 48.714638671875, 3.38572542994683e-98, +56, 48.7146875, 3.42679289110478e-98, +56, 49.2648828125, 1.73113405012133e-98, +56, 49.264931640625, 1.75251860795891e-98, +56, 49.81009765625, 9.02288638273931e-99, +56, 49.810146484375, 9.13660050992263e-99, +56, 50.35033203125, 4.87338593256003e-99, +56, 50.350380859375, 4.93504167152289e-99, +56, 50.885439453125, 2.62897432578778e-99, +56, 50.88548828125, 2.66302222150824e-99, +56, 51.41546875, 1.43071360755971e-99, +56, 51.41556640625, 1.46894783889895e-99, +56, 51.94056640625, 8.12763956845104e-100, +56, 51.9406640625, 8.34551910155042e-100, +56, 52.4605859375, 4.58251489759803e-100, +56, 52.46068359375, 4.70835817217817e-100, +56, 52.97572265625, 2.66457725640481e-100, +56, 52.9758203125, 2.73809355167495e-100, +56, 53.48587890625, 1.52026667140348e-100, +56, 53.4859765625, 1.5636427659068e-100, +56, 53.99134765625, 8.99584141358291e-101, +56, 53.9914453125, 9.25372909114439e-101, +56, 54.49212890625, 5.32825924303324e-101, +56, 54.4922265625, 5.48250901435612e-101, +56, 54.9883203125, 3.11278188657358e-101, +56, 54.98841796875, 3.20543677910749e-101, +56, 55.48021484375, 1.86269305932801e-101, +56, 55.4803125, 1.91846988478933e-101, +57, 38.0996875, 2.20476439543612e-92, +57, 38.099736328125, 2.22917432379422e-92, +57, 38.737333984375, 6.34433356523382e-93, +57, 38.7373828125, 6.41479399056003e-93, +57, 39.370830078125, 1.91018618887989e-93, +57, 39.37087890625, 1.93131173925967e-93, +57, 40.000078125, 5.92216057314857e-94, +57, 40.000126953125, 5.98791393861005e-94, +57, 40.625078125, 1.90309216004904e-94, +57, 40.625126953125, 1.92431835469877e-94, +57, 41.245830078125, 6.38398110903664e-95, +57, 41.24587890625, 6.45498354446764e-95, +57, 41.862236328125, 2.20268568579443e-95, +57, 41.86228515625, 2.22728247906098e-95, +57, 42.474248046875, 7.79068157690964e-96, +57, 42.474296875, 7.87885966415e-96, +57, 43.0819140625, 2.88050550788237e-96, +57, 43.081962890625, 2.91318272595493e-96, +57, 43.68513671875, 1.09806112159568e-96, +57, 43.685185546875, 1.11057160166479e-96, +57, 44.2838671875, 4.30562812876992e-97, +57, 44.283916015625, 4.35507143677268e-97, +57, 44.87810546875, 1.7530232640245e-97, +57, 44.878154296875, 1.7731758707715e-97, +57, 45.46775390625, 7.31286187931292e-98, +57, 45.467802734375, 7.39751767287751e-98, +57, 46.052763671875, 3.11976304411238e-98, +57, 46.0528125, 3.15638274069021e-98, +57, 46.633134765625, 1.37464423777275e-98, +57, 46.63318359375, 1.39093953120416e-98, +57, 47.208818359375, 6.24536630012012e-99, +57, 47.2088671875, 6.31989226309693e-99, +57, 47.779716796875, 2.88489889714976e-99, +57, 47.779765625, 2.91990162728214e-99, +57, 48.34587890625, 1.38459867556409e-99, +57, 48.345927734375, 1.40146037072031e-99, +57, 48.907158203125, 6.71827295305273e-100, +57, 48.90720703125, 6.80152139672612e-100, +57, 49.463603515625, 3.36417686184697e-100, +57, 49.46365234375, 3.40624440071944e-100, +57, 50.0151171875, 1.70838155932608e-100, +57, 50.015166015625, 1.73011766047011e-100, +57, 50.561748046875, 8.96377195112949e-101, +57, 50.561796875, 9.07844496707364e-101, +57, 51.1033984375, 4.7573624982879e-101, +57, 51.103447265625, 4.81906515869594e-101, +57, 51.64001953125, 2.52428955803692e-101, +57, 51.6401171875, 2.59192149716193e-101, +57, 52.1717578125, 1.39187870966602e-101, +57, 52.17185546875, 1.42956730803746e-101, +57, 52.698515625, 7.7317500805067e-102, +57, 52.69861328125, 7.94501950652444e-102, +57, 53.220390625, 4.4082211286455e-102, +57, 53.22048828125, 4.53055204196072e-102, +57, 53.73728515625, 2.47396166798242e-102, +57, 53.7373828125, 2.54499159923448e-102, +57, 54.2494921875, 1.45907071692507e-102, +57, 54.24958984375, 1.50072529856044e-102, +57, 54.75681640625, 8.32179730748228e-103, +57, 54.7569140625, 8.56822893627666e-103, +57, 55.2596484375, 4.99089804791844e-103, +57, 55.25974609375, 5.1376157827554e-103, +57, 55.757890625, 2.93846786006917e-103, +57, 55.75798828125, 3.02626005750667e-103, +57, 56.25173828125, 1.71972275925121e-103, +57, 56.2518359375, 1.77242201439855e-103, +57, 56.74138671875, 1.00746867642176e-103, +57, 56.741484375, 1.03914712466117e-103, +58, 38.841474609375, 2.28962685408854e-94, +58, 38.8415234375, 2.31583571384595e-94, +58, 39.478828125, 6.65279878387051e-95, +58, 39.478876953125, 6.72851011961114e-95, +58, 40.11203125, 1.98889585849889e-95, +58, 40.112080078125, 2.0116031211386e-95, +58, 40.741083984375, 6.15547181773793e-96, +58, 40.7411328125, 6.22611457465467e-96, +58, 41.365986328125, 1.98535700187755e-96, +58, 41.36603515625, 2.00813333128919e-96, +58, 41.986640625, 6.56800883846017e-97, +58, 41.986689453125, 6.64407409629831e-97, +58, 42.603095703125, 2.27151430941761e-97, +58, 42.60314453125, 2.29779962665845e-97, +58, 43.21525390625, 8.08887967205788e-98, +58, 43.215302734375, 8.18281575271904e-98, +58, 43.82306640625, 2.95592121751972e-98, +58, 43.823115234375, 2.99061314771485e-98, +58, 44.42658203125, 1.13134888356557e-98, +58, 44.426630859375, 1.14457524376905e-98, +58, 45.025654296875, 4.41845285569886e-99, +58, 45.025703125, 4.47048673389212e-99, +58, 45.620283203125, 1.77714624291313e-99, +58, 45.62033203125, 1.79825016216838e-99, +58, 46.210419921875, 7.34443777835212e-100, +58, 46.21046875, 7.43260970647061e-100, +58, 46.796064453125, 3.14964704226534e-100, +58, 46.79611328125, 3.18755872885081e-100, +58, 47.377119140625, 1.38201826867972e-100, +58, 47.37716796875, 1.39878290995527e-100, +58, 47.95353515625, 6.19027397147059e-101, +58, 47.953583984375, 6.26644970781979e-101, +58, 48.5253125, 2.85831172869441e-101, +58, 48.525361328125, 2.89384123773075e-101, +58, 49.09240234375, 1.35697005525987e-101, +58, 49.092451171875, 1.37396450788758e-101, +58, 49.65470703125, 6.51873789254857e-102, +58, 49.654755859375, 6.60202992320111e-102, +58, 50.212275390625, 3.23653359270438e-102, +58, 50.21232421875, 3.2783090214757e-102, +58, 50.76505859375, 1.65267733466975e-102, +58, 50.765107421875, 1.67409628228237e-102, +58, 51.31291015625, 8.39865374766313e-103, +58, 51.3130078125, 8.62296916999248e-103, +58, 51.8559765625, 4.43898857454993e-103, +58, 51.85607421875, 4.55876608676698e-103, +58, 52.39416015625, 2.38284566979309e-103, +58, 52.3942578125, 2.44798937063255e-103, +58, 52.9274609375, 1.29896683738751e-103, +58, 52.92755859375, 1.33500351596253e-103, +58, 53.45587890625, 7.16661264811987e-104, +58, 53.4559765625, 7.36908508006679e-104, +58, 53.9794140625, 3.97139434881222e-104, +58, 53.97951171875, 4.08676376045491e-104, +58, 54.49826171875, 2.31430475778334e-104, +58, 54.498359375, 2.38084236991499e-104, +58, 55.0122265625, 1.31587661343037e-104, +58, 55.01232421875, 1.354675556019e-104, +58, 55.52150390625, 7.55721877752536e-105, +58, 55.5216015625, 7.78550839762316e-105, +58, 56.02619140625, 4.38540257957703e-105, +58, 56.0262890625, 4.52070576457663e-105, +58, 56.526484375, 2.63611015718921e-105, +58, 56.52658203125, 2.71673162725835e-105, +58, 57.02228515625, 1.52363825877265e-105, +58, 57.0223828125, 1.57187635540744e-105, +58, 57.513984375, 9.12003014967339e-106, +58, 57.51408203125, 9.40921222802051e-106, +}; + +// +// A bunch of helper functions used for calculating the coefficients: +// +mp_t factorial(unsigned n) +{ + static boost::array<boost::array<mp_t, 1>, 201> result; + static bool init = false; + if(!init) + { + unsigned k = 1; + mp_t fact = 1; + do{ + result[k-1][0] = fact; + fact *= k++; + } + while(k < result.size()); + init = true; + } + //static const int array_size = result.size(); + if(n < result.size()) + return result[n][0]; + + unsigned i = (unsigned)result.size()-1; + mp_t r = result[i][0]; + while(i < n) + r *= ++i; + return r; +} + +template <class T> +T binomial(int n, int k, T) +{ + T result; + if(k < 0) + { + result = 0; + } + else if(k > n) + { + result = 1; + } + else + { + result = factorial(n); + result /= factorial(k); + result /= factorial(n-k); + } + return result; +} +// +// Functions for creating the matrices that generate the coefficents. +// See http://my.fit.edu/~gabdo/gamma.txt and http://www.rskey.org/gamma.htm +// +template <class T> +matrix<T> make_B(unsigned n, T) +{ + matrix<T> result(n, n); + for(unsigned i = 0; i < n; ++i) + { + for(unsigned j = 0; j < n; ++j) + { + if(i == 0) + result(i, j) = 1; + else if(j >= i) + { + T r = binomial(i+j-1, j-i, T()); + if((j-i) %2) + r = -r; + result(i, j) = r; + } + else + result(i, j) = 0; + } + } + return result; +} + +template <class T> +matrix<T> make_C(unsigned n, T) +{ + matrix<T> result(n, n); + for(unsigned i = 0; i < n; ++i) + { + for(unsigned j = 0; j < n; ++j) + { + if((i==0) && (j == 0)) + result(i, j) = 0.5; + else if(j > i) + result(i, j) = 0; + else + { + T r = 0; + for(unsigned k = 0; k <= i; ++k) + { + r += binomial(2*i, 2*k, T()) * binomial(k, k+j-i, T()); + } + if((i-j)%2) + r = -r; + result(i, j) = r; + } + } + } + return result; +} + +template <class T> +matrix<T> make_D(unsigned n, T) +{ + matrix<T> result(n, n); + for(unsigned i = 0; i < n; ++i) + { + for(unsigned j = 0; j < n; ++j) + { + if(i != j) + result(i, j) = 0; + else if(i == 0) + result(i, j) = 1; + else if(i == 1) + result(i, j) = -1; + else + { + T r = result(i-1, i-1) * (2 * (2*i - 1)); + r /= (i-1); + result(i, j) = r; + } + } + } + return result; +} + +template <class T> +matrix<T> make_F(unsigned n, T g) +{ + using namespace std; + matrix<T> result(n, 1); + for(unsigned i = 0; i < n; ++i) + { + T r = factorial(2 * i); + r /= factorial(i); + r *= exp(double(i) + g + 0.5); + r /= ldexp(1.0, (2*i)-1); + r /= pow(g + i + 0.5, (long)i); + r /= sqrt(g + i + 0.5); + result(i, 0) = r; + } + return result; +} + +template <class T> +struct lanczos_info +{ + int n; // number of coefficients + T r; // the arbitrary parameter + std::vector<T> c; // the coefficients + T err; // error found +}; +// +// Create the coefficients, caching previous matrix values as appropriate: +// +template <class T> +lanczos_info<T> generate_lanczos(unsigned n, T g) +{ + static unsigned last_n = 0; + static matrix<T> last_prefix; + + matrix<T> B, C, D; + matrix<T> F, P, E, T1, T2; + + if(n == last_n) + { + F = make_F(n, g); + P = prod(last_prefix, F); + } + else + { + B = make_B(n, g); + C = make_C(n, g); + D = make_D(n, g); + F = make_F(n, g); + + T1 = prod(D, B); + T2 = prod(T1, C); + P = prod(T2, F); + + last_n = n; + last_prefix = T2; + } + + lanczos_info<T> result; + result.n = n; + result.r = g; + for(unsigned i = 0; i < n; ++i) + result.c.push_back(P(i, 0)); + + return result; +} +// +// Stopwatch for measuring performance: +// +template <class Clock> +struct stopwatch +{ + typedef typename Clock::duration duration; + stopwatch() + { + m_start = Clock::now(); + } + duration elapsed() + { + return Clock::now() - m_start; + } + void reset() + { + m_start = Clock::now(); + } + +private: + typename Clock::time_point m_start; +}; +// +// Returns the factorials and half factorials: +// +template <class T> +std::vector<std::vector<T> > const & get_test_data() +{ + // returns factorials and half factorials in the range [0, 100]: + static std::vector<std::vector<T> > data; + if(data.empty()) + { + mp_t fact = 1; + int k = 1; + std::vector<T> item; + do + { + data.push_back(item); + data.back().push_back(k-1); + data.back().push_back(static_cast<T>(fact)); + data.back().push_back(static_cast<T>(log(fact))); + fact = fact * T(k++); + }while(k < 100); + + fact = 0.5; + mp_t srpi = sqrt(boost::math::constants::pi<mp_t>()); + mp_t mul = 1.5; + do{ + data.push_back(item); + data.back().push_back(static_cast<T>(mul-1)); + data.back().push_back(static_cast<T>(fact*srpi)); + data.back().push_back(static_cast<T>(log(fact*srpi))); + fact *= mul; + mul += 1; + }while(mul < 100); + } + + return data; +} + +struct sort_on_0 +{ + template<class T> + bool operator ()(const T& a, const T& b) + { + return ((a[0]) < (b[0])); + } +}; +// +// Get test data for points near 0, 1, 2 etc. +template <class T> +std::vector<std::vector<T> > const & get_test_data_near_x(T x) +{ + // + // this *must* be called with a *very* high precision + // type T in order to stand any chance of long double + // precision results: + // + using namespace std; + using namespace boost::math; + static std::vector<std::vector<T> > data; + static T last_x(-10000); + if(last_x != x) + data.clear(); + if(!data.size()) + { + last_x = x; + std::vector<T> item; + for(int i = -4; i > -20; --i) + { + double val = ldexp(2.0, i); + data.push_back(item); + data.back().push_back(val+x); + data.back().push_back(tgamma(T(val)+x)); + data.back().push_back(lgamma(T(val)+x)); + data.push_back(item); + data.back().push_back(-val+x); + data.back().push_back(tgamma(T(-val)+x)); + data.back().push_back(lgamma(T(-val)+x)); + } + T v = x-0.5; + T interval = T(1)/8; + while(v <= x+0.5) + { + if((floor(v) != v) || (v > 0)) + { + data.push_back(item); + data.back().push_back(v); + data.back().push_back(tgamma(v)); + data.back().push_back(lgamma(v)); + } + v += interval; + } + // + // sort data: + // + std::sort(data.begin(), data.end(), sort_on_0()); + } + return data; +} + +template <class T> +std::vector<std::vector<T> > const & get_test_data_near_1() +{ + return get_test_data_near_x(T(1)); +} + +template <class T> +std::vector<std::vector<T> > const & get_test_data_near_2() +{ + return get_test_data_near_x(T(2)); +} + +template <class T> +std::vector<std::vector<T> > const& get_random_test_data() +{ + static std::vector<std::vector<T> > data; + if (data.empty()) + { + boost::random::mt19937_64 gen; + boost::random::uniform_real_distribution<T> dist(1e-30, 100); + for (unsigned i = 0; i < 100; ++i) + { + T value = dist(gen); + T result = static_cast<T>(boost::math::tgamma(mp_t(value) + 1)); + data.push_back(std::vector<T>({value, result})); + } + } + return data; +} + +// +// Converts Lanczos approximation into rational form via +// polynomial arithmetic: +// +template <class T> +struct lanczos_rational +{ + std::vector<T> num, denom; + int N; + T g; + + T gamma(T z) + { + using namespace std; + BOOST_ASSERT(num.size() == denom.size()); + BOOST_ASSERT(num.size() == N); + T zgh = z + g - T(0.5); + T prefix = pow(zgh, T(z - 0.5)) / exp(zgh); + T s1, s2; + if(z < 1) + { + s1 = num[N-1]; + s2 = denom[N-1]; + for(unsigned i = N-2; i >= 0; --i) + { + s1 *= z; + s2 *= z; + s1 += num[i]; + s2 += num[i]; + } + s1 /= s2; + return prefix * s1; + } + else + { + z = 1/z; + s1 = num[0]; + s2 = denom[0]; + for(int i = 1; i < N; ++i) + { + s1 *= z; + s2 *= z; + s1 += num[i]; + s2 += denom[i]; + } + s1 /= s2; + return prefix * s1; + } + } + T factorial(T z) + { + return this->gamma(z+1); + } + template <class U> + lanczos_rational(const lanczos_info<U>& info) + { + U l_denom_coef[2] = { 0, 1 }; + boost::math::tools::polynomial<U> l_denom(l_denom_coef, 1), l_num(info.c[1]); + for(unsigned i = 2; i < info.c.size(); ++i) + { + l_denom_coef[0] = i - 1; + boost::math::tools::polynomial<U> bot(l_denom_coef, 1), top(info.c[i]); + l_num *= bot; + top *= l_denom; + l_denom *= bot; + l_num += top; + } + l_num += l_denom * info.c[0]; + for(unsigned i = 0; i < info.c.size(); ++i) + { + num.push_back(boost::math::tools::real_cast<T>(l_num[i])); + denom.push_back(boost::math::tools::real_cast<T>(l_denom[i])); + } + //std::cout << l_num << std::endl; + //std::cout << l_denom << std::endl; + BOOST_ASSERT(num.size() == l_num.degree()+1); + BOOST_ASSERT(denom.size() == l_denom.degree()+1); + g = boost::math::tools::real_cast<T>(info.r); + N = info.n; + /* + for(unsigned i = 0; i < num.size(); ++i) + std::cout << num[i] << " "; + std::cout << std::endl; + for(unsigned i = 0; i < denom.size(); ++i) + std::cout << denom[i] << " "; + std::cout << std::endl; + */ + } +}; +// +// Code to test an approximation against the factorials and +// half factorials, returns the max error found: +// +template <class T, class R> +T get_max_error(const lanczos_info<T>& dat, R, double* time = nullptr) +{ + R max_error = 0; + std::vector<std::vector<R> > const & tests1 = get_test_data<R>(); + std::vector<std::vector<R> > const & tests2 = get_random_test_data<R>(); + + std::vector<std::vector<R> > tests(tests1.begin(), tests1.end()); + tests.insert(tests.end(), tests2.begin(), tests2.end()); + + lanczos_rational<R> rational(dat); + + stopwatch<boost::chrono::high_resolution_clock> w; + + for(unsigned i = 0; i < tests.size(); ++i) + { + R input = tests[i][0]; + R expected = tests[i][1]; + if(std::numeric_limits<R>::is_specialized && (boost::math::tools::real_cast<R>(tests[i][1]) > (std::numeric_limits<R>::max)())) + continue; + + R gamr = rational.factorial(input); + if(std::numeric_limits<R>::is_specialized && (gamr > (std::numeric_limits<R>::max)())) + continue; + R err = boost::math::relative_difference(gamr, expected); + if(err > max_error) + max_error = err; + } + + if (time) + * time = boost::chrono::duration_cast<boost::chrono::duration<double>>(w.elapsed()).count(); + + return max_error; +} + +template <class T> +T get_max_error_sterling(double* time = nullptr) +{ + std::vector<std::vector<T> > const& tests1 = get_test_data<T>(); + std::vector<std::vector<T> > const& tests2 = get_random_test_data<T>(); + + std::vector<std::vector<T> > tests(tests1.begin(), tests1.end()); + tests.insert(tests.end(), tests2.begin(), tests2.end()); + + T max_err = 0; + + stopwatch<boost::chrono::high_resolution_clock> w; + + for (unsigned i = 0; i < tests.size(); ++i) + { + T loc = tests[i][0] + 1; + T found = boost::math::detail::gamma_imp(loc, boost::math::policies::policy<>(), boost::math::lanczos::undefined_lanczos()); + T expected = tests[i][1]; + T err = boost::math::relative_difference(expected, found); + if (err > max_err) + max_err = err; + } + + if(time) + *time = boost::chrono::duration_cast<boost::chrono::duration<double>>(w.elapsed()).count(); + + return max_err; +} + +// +// This is what prints the "best" approximation out as code: +// +template <class T> +void print_code(const lanczos_info<T>& l, const char* name, int precision = std::numeric_limits<T>::max_digits10, int precision2 = std::numeric_limits<T>::digits) +{ + std::cout << std::scientific << std::setprecision(precision); + using namespace std; + lanczos_info<T> l2(l); + T factor = exp(l.r); + for(unsigned k = 0; k < l2.c.size(); ++k) + l2.c[k] /= factor; + + lanczos_rational<T> rat(l); + T max_term = 0; + for(unsigned i = 0; i < rat.denom.size(); ++i) + { + if(rat.denom[i] > max_term) + max_term = rat.denom[i]; + } + const char* denom_type; + const char* cast_type; + const char* suffix_type; + if(max_term < (std::numeric_limits<boost::uint16_t>::max)()) + { + denom_type = "boost::uint16_t"; + cast_type = "static_cast<boost::uint16_t>"; + suffix_type = "u"; + } + else if(max_term < (std::numeric_limits<boost::uint32_t>::max)()) + { + denom_type = "boost::uint32_t"; + cast_type = "static_cast<boost::uint32_t>"; + suffix_type = "u"; + } +#ifdef BOOST_HAS_LONG_LONG + else if(max_term < (std::numeric_limits<boost::uint64_t>::max)()) + { + denom_type = "boost::uint64_t"; + cast_type = ""; + suffix_type = "uLL"; + } +#endif + else + { + denom_type = "T"; + cast_type = "static_cast<T>"; + suffix_type = "L"; + } + + std::cout << + "//\n" + "// Lanczos Coefficients for N=" << l.n << " G=" << l.r << "\n" + "// Max experimental error (with "; + if(std::strlen(name) == 0) + std::cout << "arbitary"; + else + std::cout << name; + std::cout << " precision arithmetic) " << l.err << + "\n// Generated with compiler: " << BOOST_COMPILER << " on " << BOOST_PLATFORM << " at " << __DATE__ << "\n" + "// Type precision was " << precision2 << " bits or " << precision << " max_digits10\n" + "//\n" + "struct lanczos" << l.n << name << " : public mpl::int_<" << precision2 << ">\n" + "{\n" + " template <class T>\n" + " static T lanczos_sum(const T& z)\n" + " {\n" + " static const T num[" << rat.num.size() << "] = {\n"; + + for(unsigned i = 0; i < rat.num.size(); ++i) + { + if(precision <= std::numeric_limits<long double>::digits10) + std::cout << " static_cast<T>(" << rat.num[i] << "L)"; + else + std::cout << " static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, " << precision2 << ", " << rat.num[i] << "))"; + if(i != rat.num.size() - 1) + std::cout << ","; + std::cout << "\n"; + } + std::cout << + " };\n" + " static const " << denom_type << " denom[" << rat.denom.size() << "] = {\n"; + for(unsigned i = 0; i < rat.denom.size(); ++i) + { + if(precision <= std::numeric_limits<long double>::digits10) + std::cout << " " << cast_type << "(" << rat.denom[i] << suffix_type << ")"; + else + std::cout << " static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, " << precision2 << ", " << rat.denom[i] << "))"; + if(i != rat.denom.size() - 1) + std::cout << ","; + std::cout << "\n"; + } + std::cout << + " };\n" + " return boost::math::tools::evaluate_rational(num, denom, z);\n" + " }\n\n" + " template <class T>\n" + " static T lanczos_sum_expG_scaled(const T& z)\n" + " {\n" + " static const T num[" << rat.num.size() << "] = {\n"; + + for(unsigned i = 0; i < rat.num.size(); ++i) + { + if (precision <= std::numeric_limits<long double>::digits10) + std::cout << " static_cast<T>(" << (rat.num[i]/factor) << "L)"; + else + std::cout << " static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, " << precision2 << ", " << (rat.num[i]/factor) << "))"; + if(i != rat.num.size() - 1) + std::cout << ","; + std::cout << "\n"; + } + std::cout << + " };\n" + " static const " << denom_type << " denom[" << rat.denom.size() << "] = {\n"; + for(unsigned i = 0; i < rat.denom.size(); ++i) + { + if (precision <= std::numeric_limits<long double>::digits10) + std::cout << " " << cast_type << "(" << rat.denom[i] << suffix_type << ")"; + else + std::cout << " static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, " << precision2 << ", " << rat.denom[i] << "))"; + if(i != rat.denom.size() - 1) + std::cout << ","; + std::cout << "\n"; + } + std::cout << + " };\n" + " return boost::math::tools::evaluate_rational(num, denom, z);\n" + " }\n\n"; + + std::cout << + "\n template<class T>\n" + " static T lanczos_sum_near_1(const T& dz)\n" + " {\n" + " static const T d[" << l2.n-1 << "] = {\n"; + + factor = sqrt((l.r + 0.5)/boost::math::constants::e<T>()) / exp(l.r); + + for(int i = 1; i < l.n; ++i) + { + if (precision <= std::numeric_limits<long double>::digits10) + std::cout << " static_cast<T>(" << l.c[i]*factor << "L)"; + else + std::cout << " static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, " << precision2 << ", " << l.c[i] * factor << "))"; + if(i != l.n - 1) + std::cout << ","; + std::cout << "\n"; + } + std::cout << + " };\n" + " T result = 0;\n" + " for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k)\n" + " {\n" + " result += (-d[k-1]*dz)/(k*dz + k*k);\n" + " }\n" + " return result;\n" + " }\n"; + + std::cout << + "\n template<class T>\n" + " static T lanczos_sum_near_2(const T& dz)\n" + " {\n" + " static const T d[" << l2.n-1 << "] = {\n"; + + factor = pow(boost::math::constants::e<T>()/(l.r+1.5), T(1.5)) * exp(l.r); + //pow((l.r + 1.5)/boost::math::constants::e<T>(), 1.5) / exp(l.r); + + for(int i = 1; i < l.n; ++i) + { + if (precision <= std::numeric_limits<long double>::digits10) + std::cout << " static_cast<T>(" << l.c[i]/factor << "L),\n"; + else + std::cout << " static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, " << precision2 << ", " << l.c[i]/factor << ")),\n"; + } + std::cout << + " };\n" + " T result = 0;\n" + " T z = dz + 2;\n" + " for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k)\n" + " {\n" + " result += (-d[k-1]*dz)/(z + k*z + k*k - 1);\n" + " }\n" + " return result;\n" + " }\n\n" + " static double g(){ return " << l.r << "; }\n" + "};\n\n"; +} +// +// Print out the test values: +// +void print_test_values(const std::vector<std::vector<mp_t> >& v, const char* name, int offset = 1) +{ + std::cout << std::setprecision(110); + std::cout << + " static const boost::array<boost::array<T, 3>, " << v.size() << "> " << name << " = {\n"; + for(unsigned i = 0; i < v.size(); ++i) + { + std::cout << " SC_(" << (v[i][0] + offset) << "), SC_(" << v[i][1] << "), SC_(" << v[i][2] << "),\n"; + } + std::cout << " };\n\n"; +} +// +// Get the error for a specific approximation, and print out it's code: +// +void calculate_lanczos_spot(int n, mp_t r, const char* suffix = "") +{ + lanczos_info<mp_t> info = generate_lanczos(n, r); + // note error is calculated at high precision: + info.err = get_max_error(info, r); + print_code(info, suffix); +} +// +// Scan the sweet-spots for the best approximation: +// +template <class T> +void find_best_lanczos(const char* name, T eps, int max_scan = 100) +{ + using namespace std; + + double exec_time; + + std::cout << "Enter value for N, or 0 to scan for best approximation: "; + int N; + std::cin >> N; + + if (N == 0) + { + T sterling_err = get_max_error_sterling<T>(&exec_time); + + std::cout << "Max error from generic Sterling approximation was: " << static_cast<int>(sterling_err / eps) << "eps (in " << (int)(exec_time * 1000) << "ms)" << std::endl; + + lanczos_info<mp_t> best; + best.err = 100; // best case had better be better than this! + + std::cout << std::setw(20) << std::right << "N" << std::setw(20) << std::right << "g" << std::setw(20) << std::right << "eps" << std::setw(20) << std::right << "time (ms)\n"; + + for (int i = 0; i < sizeof(sweet_spots) / sizeof(sweet_spots[0]); ++i) + { + if ((sweet_spots[i].err < eps * 10) && (sweet_spots[i].N < max_scan)) + { + lanczos_info<mp_t> info = generate_lanczos(sweet_spots[i].N, mp_t(sweet_spots[i].g)); + mp_t err = get_max_error(info, eps, &exec_time); + if (err / eps < 1000) + { + std::cout << std::setprecision(14) << std::fixed << std::setw(20) << std::right << sweet_spots[i].N + << std::setw(20) << std::right << sweet_spots[i].g << std::setw(20) << std::right << static_cast<int>(err / eps) + << std::setw(20) << std::right << (int)(exec_time * 1000) << std::endl; + } + if (err < best.err) + { + best = info; + best.err = err; + } + } + } + std::cout << std::endl; + + if (best.err < 100) + print_code(best, name, std::numeric_limits<T>::max_digits10, std::numeric_limits<T>::digits); + else + std::cout << "Sorry, no viable approximation was found!!" << std::endl; + } + else + { + // + // Test a specific N and g: + // + std::cout << "Enter a value for g: "; + double g; + std::cin >> g; + lanczos_info<mp_t> info = generate_lanczos(N, mp_t(g)); + mp_t err = get_max_error(info, eps, &exec_time); + + std::cout << "N = " << N << std::endl; + std::cout << "g = " << g << std::endl; + std::cout << "eps error = " << static_cast<int>(err / eps) << std::endl; + std::cout << "Test time (ms) = " << static_cast<int>(exec_time * 1000) << std::endl; + print_code(info, name, std::numeric_limits<T>::max_digits10, std::numeric_limits<T>::digits); + } +} + +void scan_for_sweet_spots(int N) +{ + mp_t r = N * 0.66; + lanczos_info<mp_t> lower, upper(generate_lanczos(N + 1, r)); + r += 0.1; + while (r < N) + { + lower = upper; + upper = generate_lanczos(N + 1, r); + + if (lower.c.back() * upper.c.back() < 0) + { + std::pair<mp_t, mp_t> location = boost::math::tools::bisect([N](const mp_t& pos) + { + return generate_lanczos(N + 1, pos).c.back(); + }, r - 0.1, r, boost::math::tools::eps_tolerance<mp_t>(20)); + mp_t err = get_max_error(generate_lanczos(N, location.first), std::numeric_limits<mp_t>::epsilon()); + std::cout << std::setprecision(15) << N << ", " << location.first << ", " << err << std::endl; + err = get_max_error(generate_lanczos(N, location.second), std::numeric_limits<mp_t>::epsilon()); + std::cout << std::setprecision(15) << N << ", " << location.second << ", " << err << std::endl; + //std::cout << std::setprecision(15) << N << ", " << location.first << ", " << location.second << std::endl; + } + + r += 0.1; + } +} + +int main(int argc, char*argv []) +{ + bool test_double(false), test_long(false), test_float(false), test_quad(false), test_mp(false), spots(false), test_data(false), find_sweet(false); + + if(argc < 2) + { + std::cout << + "Useage:\n" + " -float test type float for the best approximation\n" + " -double test type double for the best approximation\n" + " -long-double test type long double for the best approximation\n" + " -quad test quad precision for the best approximation\n" + " -MP test current multiprecision type for the best approximation\n" + " -spots print out the best cases found in previous runs\n" + " -sweet Scan for more sweet spots for the arbitary parameter G: these " + " will need to cut and pasted into the big table at the start of this file" + " in order to search for greater precision approximations than otherwise supported." + " -data print out the test data\n" << std::flush; + return 1; + } + + for(int i = 1; i < argc; ++i) + { + if(std::strcmp(argv[i], "-float") == 0) + test_float = true; + else if(std::strcmp(argv[i], "-double") == 0) + test_double = true; + else if(std::strcmp(argv[i], "-long-double") == 0) + test_long = true; + else if(std::strcmp(argv[i], "-quad-float") == 0) + test_quad = true; + else if(std::strcmp(argv[i], "-MP") == 0) + test_mp = true; + else if(std::strcmp(argv[i], "-spots") == 0) + spots = true; + else if(std::strcmp(argv[i], "-data") == 0) + test_data = true; + else if(std::strcmp(argv[i], "-sweet") == 0) + find_sweet = true; + } + + if(spots) + { + // these are optimal N and R from Pugh: + calculate_lanczos_spot(61, 63.192152); + calculate_lanczos_spot(31, 32.080670); + calculate_lanczos_spot(6, 5.581); + calculate_lanczos_spot(11, 10.900511); + calculate_lanczos_spot(13, 13.144565); + calculate_lanczos_spot(22, 22.61891); + // these are the best cases we've already determined + // from previous runs: + calculate_lanczos_spot(6, 1.428456135094165802001953125); + calculate_lanczos_spot(13, 6.024680040776729583740234375); + calculate_lanczos_spot(17, 12.2252227365970611572265625); + calculate_lanczos_spot(24, 20.3209821879863739013671875); + } + if(test_float) + { + find_best_lanczos("float", std::numeric_limits<float>::epsilon()); + } + if(test_double) + { + find_best_lanczos("double", std::numeric_limits<double>::epsilon()); + } + + if(test_long) + { + find_best_lanczos("long_double", std::numeric_limits<long double>::epsilon()); + } + if(test_quad) + { + find_best_lanczos("quad_float", std::numeric_limits<boost::multiprecision::cpp_bin_float_quad>::epsilon()); + } +#ifdef MP_TYPE + if(test_mp) + { + find_best_lanczos("MP", std::numeric_limits<MP_TYPE>::epsilon()); + } +#endif + if(test_data) + { + std::cout << "Test Data follows:\n\n"; + + std::vector<std::vector<mp_t> > const & tests = get_test_data<mp_t>(); + print_test_values(tests, "factorials"); + print_test_values(get_test_data_near_1<mp_t>(), "near_1", 0); + print_test_values(get_test_data_near_2<mp_t>(), "near_2", 0); + print_test_values(get_test_data_near_x<mp_t>(mp_t(0)), "near_0", 0); + print_test_values(get_test_data_near_x<mp_t>(mp_t(-10)), "near_m10", 0); + print_test_values(get_test_data_near_x<mp_t>(mp_t(-55)), "near_m55", 0); + } + if (find_sweet) + { + unsigned last_index = sizeof(sweet_spots) / sizeof(sweet_spots[0]) - 1; + for(unsigned N = sweet_spots[last_index].N + 1; N < sweet_spots[last_index].N + 11; ++N) + scan_for_sweet_spots(N); + } + return 0; +} + + + diff --git a/src/boost/libs/math/tools/legendre_data.cpp b/src/boost/libs/math/tools/legendre_data.cpp new file mode 100644 index 00000000..b011c77e --- /dev/null +++ b/src/boost/libs/math/tools/legendre_data.cpp @@ -0,0 +1,101 @@ +// (C) Copyright John Maddock 2007. +// 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 <boost/math/special_functions/legendre.hpp> +#include <boost/math/special_functions/gamma.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + + +template<class T> +boost::math::tuple<T, T, T, T> legendre_p_data(T n, T x) +{ + n = floor(n); + T r1 = legendre_p(boost::math::tools::real_cast<int>(n), x); + T r2 = legendre_q(boost::math::tools::real_cast<int>(n), x); + return boost::math::make_tuple(n, x, r1, r2); +} + +template<class T> +boost::math::tuple<T, T, T, T> assoc_legendre_p_data(T n, T x) +{ + static boost::mt19937 r; + int l = real_cast<int>(floor(n)); + boost::uniform_int<> ui((std::max)(-l, -40), (std::min)(l, 40)); + int m = ui(r); + T r1 = legendre_p(l, m, x); + return boost::math::make_tuple(n, m, x, r1); +} + +int main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + if(strcmp(argv[1], "--legendre2") == 0) + { + do{ + if(0 == get_user_parameter_info(arg1, "l")) + return 1; + if(0 == get_user_parameter_info(arg2, "x")) + return 1; + arg1.type |= dummy_param; + arg2.type |= dummy_param; + + data.insert(&legendre_p_data<mp_t>, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + } + else if(strcmp(argv[1], "--legendre3") == 0) + { + do{ + if(0 == get_user_parameter_info(arg1, "l")) + return 1; + if(0 == get_user_parameter_info(arg2, "x")) + return 1; + arg1.type |= dummy_param; + arg2.type |= dummy_param; + + data.insert(&assoc_legendre_p_data<mp_t>, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + } + + + std::cout << "Enter name of test data file [default=legendre_p.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "legendre_p.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + line.erase(line.find('.')); + write_code(ofs, data, line.c_str()); + + return 0; +} + diff --git a/src/boost/libs/math/tools/log1p_expm1_data.cpp b/src/boost/libs/math/tools/log1p_expm1_data.cpp new file mode 100644 index 00000000..3ccdd01a --- /dev/null +++ b/src/boost/libs/math/tools/log1p_expm1_data.cpp @@ -0,0 +1,59 @@ +// (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 <fstream> +#include <boost/math/tools/test_data.hpp> +#include <boost/math/special_functions/log1p.hpp> +#include <boost/math/special_functions/expm1.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace std; + +struct data_generator +{ + boost::math::tuple<mp_t, mp_t> operator()(mp_t z) + { + return boost::math::make_tuple(boost::math::log1p(z), boost::math::expm1(z)); + } +}; + +int main(int argc, char* argv[]) +{ + parameter_info<mp_t> arg1; + test_data<mp_t> data; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the log1p and expm1 functions:\n\n"; + + bool cont; + std::string line; + + do{ + if(0 == get_user_parameter_info(arg1, "z")) + return 1; + data.insert(data_generator(), arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=log1p_expm1_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "log1p_expm1_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "log1p_expm1_data"); + + return 0; +} + + + + diff --git a/src/boost/libs/math/tools/mp_t.hpp b/src/boost/libs/math/tools/mp_t.hpp new file mode 100644 index 00000000..d780d272 --- /dev/null +++ b/src/boost/libs/math/tools/mp_t.hpp @@ -0,0 +1,71 @@ +// (C) Copyright John Maddock 2014. +// 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) + +#ifndef BOOST_MATH_TOOLS_MP_T +#define BOOST_MATH_TOOLS_MP_T + +#ifndef BOOST_MATH_PRECISION +#define BOOST_MATH_PRECISION 1000 +#endif + +#if defined(BOOST_MATH_USE_MPFR) + +#include <boost/multiprecision/mpfr.hpp> + +typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<BOOST_MATH_PRECISION *301L / 1000L> > mp_t; + +#else + +#include <boost/multiprecision/cpp_bin_float.hpp> + +typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<BOOST_MATH_PRECISION, boost::multiprecision::digit_base_2> > mp_t; + +#endif + +inline mp_t ConvPrec(mp_t arg, int digits) +{ + int e1, e2; + mp_t t = frexp(arg, &e1); + t = frexp(floor(ldexp(t, digits + 1)), &e2); + return ldexp(t, e1); +} + +inline mp_t relative_error(mp_t a, mp_t b) +{ + mp_t min_val = boost::math::tools::min_value<mp_t>(); + mp_t max_val = boost::math::tools::max_value<mp_t>(); + + if((a != 0) && (b != 0)) + { + // mp_tODO: use isfinite: + if(fabs(b) >= max_val) + { + if(fabs(a) >= max_val) + return 0; // one infinity is as good as another! + } + // If the result is denormalised, treat all denorms as equivalent: + if((a < min_val) && (a > 0)) + a = min_val; + else if((a > -min_val) && (a < 0)) + a = -min_val; + if((b < min_val) && (b > 0)) + b = min_val; + else if((b > -min_val) && (b < 0)) + b = -min_val; + return (std::max)(fabs((a - b) / a), fabs((a - b) / b)); + } + + // Handle special case where one or both are zero: + if(min_val == 0) + return fabs(a - b); + if(fabs(a) < min_val) + a = min_val; + if(fabs(b) < min_val) + b = min_val; + return (std::max)(fabs((a - b) / a), fabs((a - b) / b)); +} + + +#endif // BOOST_MATH_TOOLS_MP_T diff --git a/src/boost/libs/math/tools/process_perf_results.cpp b/src/boost/libs/math/tools/process_perf_results.cpp new file mode 100644 index 00000000..ecc6feb8 --- /dev/null +++ b/src/boost/libs/math/tools/process_perf_results.cpp @@ -0,0 +1,142 @@ +// Copyright John Maddock 2007. + +// 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 <map> +#include <fstream> +#include <iostream> +#include <boost/regex.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/format.hpp> +#include <boost/math/special_functions.hpp> + +std::map<std::string, double> results; + +std::map<std::string, std::string> extra_text; + +void load_file(std::string& s, std::istream& is) +{ + s.erase(); + if(is.bad()) return; + s.reserve(is.rdbuf()->in_avail()); + char c; + while(is.get(c)) + { + if(s.capacity() == s.size()) + s.reserve(s.capacity() * 3); + s.append(1, c); + } +} + +int main(int argc, const char* argv[]) +{ + // + // Set any additional text that should accumpany specific results: + // + extra_text["msvc-dist-beta-R-quantile"] = "[footnote There are a small number of our test cases where the R library fails to converge on a result: these tend to dominate the performance result.]"; + extra_text["msvc-dist-nbinom-R-quantile"] = "[footnote The R library appears to use a linear-search strategy, that can perform very badly in a small number of pathological cases, but may or may not be more efficient in \"typical\" cases]"; + extra_text["gcc-4_3_2-dist-beta-R-quantile"] = "[footnote There are a small number of our test cases where the R library fails to converge on a result: these tend to dominate the performance result.]"; + extra_text["gcc-4_3_2-dist-nbinom-R-quantile"] = "[footnote The R library appears to use a linear-search strategy, that can perform very badly in a small number of pathological cases, but may or may not be more efficient in \"typical\" cases]"; + extra_text["msvc-dist-hypergeometric-cdf"] = "[footnote This result is somewhat misleading: for small values of the parameters there is virtually no difference between the two libraries, but for large values the Boost implementation is /much/ slower, albeit with much improved precision.]"; + extra_text["msvc-dist-nt-R-quantile"] = "[footnote There are a small number of our test cases where the R library fails to converge on a result: these tend to dominate the performance result.]"; + extra_text["msvc-dist-nchisq-R-quantile"] = "[footnote There are a small number of our test cases where the R library fails to converge on a result: these tend to dominate the performance result.]"; + extra_text["gcc-4_3_2-dist-hypergeometric-cdf"] = "[footnote This result is somewhat misleading: for small values of the parameters there is virtually no difference between the two libraries, but for large values the Boost implementation is /much/ slower, albeit with much improved precision.]"; + extra_text["gcc-4_3_2-dist-nt-R-quantile"] = "[footnote There are a small number of our test cases where the R library fails to converge on a result: these tend to dominate the performance result.]"; + extra_text["gcc-4_3_2-dist-nchisq-R-quantile"] = "[footnote There are a small number of our test cases where the R library fails to converge on a result: these tend to dominate the performance result.]"; + + boost::regex e("^Testing\\s+(\\S+)\\s+(\\S+)"); + std::string f; + for(int i = 1; i < argc-1; ++i) + { + std::ifstream is(argv[i]); + load_file(f, is); + boost::sregex_iterator a(f.begin(), f.end(), e), b; + while(a != b) + { + results[(*a).str(1)] = boost::lexical_cast<double>((*a).str(2)); + ++a; + } + } + // + // Load quickbook file: + // + std::ifstream is(argv[argc-1]); + std::string bak_file = std::string(argv[argc-1]).append(".bak"); + std::ofstream os(bak_file.c_str()); + e.assign( + "\\[perf\\s+([^\\s.]+)" + "(?:" + "\\[[^\\]\\[]*" + "(?:\\[[^\\]\\[]*\\][^\\]\\[]*)?" + "\\]" + "|[^\\]]" + ")*\\]"); + std::string newfile; + while(is.good()) + { + std::getline(is, f); + os << f << std::endl; + boost::sregex_iterator i(f.begin(), f.end(), e), j; + double min = (std::numeric_limits<double>::max)(); + while(i != j) + { + std::cout << (*i).str() << std::endl << (*i).str(1) << std::endl; + std::string item = (*i).str(1); + if(results.find(item) != results.end()) + { + double r = results[item]; + if(r < min) + min = r; + } + ++i; + } + // + // Now perform the substitutions: + // + std::string newstr; + std::string tail; + i = boost::sregex_iterator(f.begin(), f.end(), e); + while(i != j) + { + std::string item = (*i).str(1); + newstr.append(i->prefix()); + if(results.find(item) != results.end()) + { + double v = results[item]; + double r = v / min; + newstr += std::string((*i)[0].first, (*i)[1].second); + newstr += "..[para "; + if(r < 1.01) + newstr += "*"; + newstr += (boost::format("%.2f") % r).str(); + if(r < 1.01) + newstr += "*"; + if(extra_text.find(item) != extra_text.end()) + { + newstr += extra_text[item]; + } + newstr += "][para ("; + newstr += (boost::format("%.3e") % results[item]).str(); + newstr += "s)]]"; + } + else + { + newstr.append(i->str()); + std::cerr << "Item " << item << " not found!!" << std::endl; + } + tail = i->suffix(); + ++i; + } + if(newstr.size()) + newfile.append(newstr).append(tail); + else + newfile.append(f); + newfile.append("\n"); + } + is.close(); + std::ofstream ns(argv[argc-1]); + ns << newfile; +} + diff --git a/src/boost/libs/math/tools/rational_tests.cpp b/src/boost/libs/math/tools/rational_tests.cpp new file mode 100644 index 00000000..67f1ca0c --- /dev/null +++ b/src/boost/libs/math/tools/rational_tests.cpp @@ -0,0 +1,365 @@ +// (C) Copyright John Maddock 2007. +// 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 <boost/random.hpp> +#include <boost/math/tools/rational.hpp> +#include <iostream> +#include <fstream> +#include "mp_t.hpp" + +int main() +{ + using namespace boost::math; + using namespace boost::math::tools; + + std::cout << std::scientific << std::setprecision(40); + + boost::mt19937 rnd; + boost::variate_generator< + boost::mt19937, + boost::uniform_int<> > gen(rnd, boost::uniform_int<>(1, 12)); + + for(unsigned i = 1; i < 12; ++i) + { + std::vector<int> coef; + for(unsigned j = 0; j < i; ++j) + { + coef.push_back(gen()); + } + std::cout << +" //\n" +" // Polynomials of order " << i-1 << "\n" +" //\n" +" static const U n" << i << "c[" << i << "] = { "; + for(unsigned j = 0; j < i; ++j) + { + if(j) + std::cout << ", "; + std::cout << coef[j]; + } + std::cout << " };\n"; + std::cout << + " static const boost::array<U, " << i << "> n" << i << "a = { "; + for(unsigned j = 0; j < i; ++j) + { + if(j) + std::cout << ", "; + std::cout << coef[j]; + } + std::cout << " };\n"; + + mp_t r1 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.125), i); + mp_t r2 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.25), i); + mp_t r3 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.75), i); + mp_t r4 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(1) - mp_t(1) / 64, i); + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.125), " << i << "),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.25), " << i << "),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.75), " << i << "),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f), " << i << "),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "a, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "a, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "a, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_polynomial(n" << i << "a, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n\n"; + + r1 = boost::math::tools::evaluate_even_polynomial(&coef[0], mp_t(0.125), i); + r2 = boost::math::tools::evaluate_even_polynomial(&coef[0], mp_t(0.25), i); + r3 = boost::math::tools::evaluate_even_polynomial(&coef[0], mp_t(0.75), i); + r4 = boost::math::tools::evaluate_even_polynomial(&coef[0], mp_t(1) - mp_t(1) / 64, i); + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.125), " << i << "),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.25), " << i << "),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.75), " << i << "),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f), " << i << "),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "a, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "a, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "a, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_even_polynomial(n" << i << "a, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n\n"; + + if(i > 1) + { + r1 = boost::math::tools::evaluate_odd_polynomial(&coef[0], mp_t(0.125), i); + r2 = boost::math::tools::evaluate_odd_polynomial(&coef[0], mp_t(0.25), i); + r3 = boost::math::tools::evaluate_odd_polynomial(&coef[0], mp_t(0.75), i); + r4 = boost::math::tools::evaluate_odd_polynomial(&coef[0], mp_t(1) - mp_t(1) / 64, i); + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.125), " << i << "),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.25), " << i << "),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.75), " << i << "),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f), " << i << "),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "a, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "a, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "a, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3 << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_odd_polynomial(n" << i << "a, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4 << "L),\n" + " tolerance);\n\n"; + } + + r1 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.125), i); + r2 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.25), i); + r3 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.75), i); + r4 = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(1) - mp_t(1) / 64, i); + + coef.clear(); + for(unsigned j = 0; j < i; ++j) + { + coef.push_back(gen()); + } + std::cout << +" //\n" +" // Rational functions of order " << i-1 << "\n" +" //\n" +" static const U d" << i << "c[" << i << "] = { "; + for(unsigned j = 0; j < i; ++j) + { + if(j) + std::cout << ", "; + std::cout << coef[j]; + } + std::cout << " };\n"; + std::cout << + " static const boost::array<U, " << i << "> d" << i << "a = { "; + for(unsigned j = 0; j < i; ++j) + { + if(j) + std::cout << ", "; + std::cout << coef[j]; + } + std::cout << " };\n"; + + mp_t r1d = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.125), i); + mp_t r2d = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.25), i); + mp_t r3d = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(0.75), i); + mp_t r4d = boost::math::tools::evaluate_polynomial(&coef[0], mp_t(1) - mp_t(1) / 64, i); + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.125), " << i << "),\n" + " static_cast<T>(" << r1/r1d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.25), " << i << "),\n" + " static_cast<T>(" << r2/r2d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.75), " << i << "),\n" + " static_cast<T>(" << r3/r3d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f), " << i << "),\n" + " static_cast<T>(" << r4/r4d << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1/r1d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2/r2d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3/r3d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "c, d" << i << "c, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4/r4d << "L),\n" + " tolerance);\n\n"; + + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "a, d" << i << "a, static_cast<T>(0.125)),\n" + " static_cast<T>(" << r1/r1d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "a, d" << i << "a, static_cast<T>(0.25)),\n" + " static_cast<T>(" << r2/r2d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "a, d" << i << "a, static_cast<T>(0.75)),\n" + " static_cast<T>(" << r3/r3d << "L),\n" + " tolerance);\n"; + std::cout << + " BOOST_CHECK_CLOSE(\n" + " boost::math::tools::evaluate_rational(n" << i << "a, d" << i << "a, static_cast<T>(1.0f - 1.0f/64.0f)),\n" + " static_cast<T>(" << r4/r4d << "L),\n" + " tolerance);\n\n"; + } + + return 0; +} + + + diff --git a/src/boost/libs/math/tools/sinc_data.cpp b/src/boost/libs/math/tools/sinc_data.cpp new file mode 100644 index 00000000..02cc61c9 --- /dev/null +++ b/src/boost/libs/math/tools/sinc_data.cpp @@ -0,0 +1,71 @@ +// (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 <boost/math/special_functions/digamma.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace std; + +float external_f; +float force_truncate(const float* f) +{ + external_f = *f; + return external_f; +} + +float truncate_to_float(mp_t r) +{ + float f = boost::math::tools::real_cast<float>(r); + return force_truncate(&f); +} + +template <class T> +T naive_sinc(T const& x) +{ + using std::sin; + return sin(x) / x; +} + +int cpp_main(int argc, char*argv []) +{ + parameter_info<mp_t> arg1; + test_data<mp_t> data; + + bool cont; + std::string line; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the sinc function:\n" + " sinc_pi(z)\n\n"; + + do{ + if(0 == get_user_parameter_info(arg1, "z")) + return 1; + data.insert(&::naive_sinc<mp_t>, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=sinc_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "sinc_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "sinc_data"); + + return 0; +} + + + diff --git a/src/boost/libs/math/tools/spherical_harmonic_data.cpp b/src/boost/libs/math/tools/spherical_harmonic_data.cpp new file mode 100644 index 00000000..2c04823e --- /dev/null +++ b/src/boost/libs/math/tools/spherical_harmonic_data.cpp @@ -0,0 +1,86 @@ +// (C) Copyright John Maddock 2007. +// 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 <boost/math/special_functions/spherical_harmonic.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include <boost/random.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; + +float extern_val; +// confuse the compilers optimiser, and force a truncation to float precision: +float truncate_to_float(float const * pf) +{ + extern_val = *pf; + return *pf; +} + + + +template<class T> +boost::math::tuple<T, T, T, T, T, T> spherical_harmonic_data(T i) +{ + static boost::mt19937 r; + + int n = real_cast<int>(floor(i)); + boost::uniform_int<> ui(0, (std::min)(n, 40)); + int m = ui(r); + + boost::uniform_real<float> ur(-2*constants::pi<float>(), 2*constants::pi<float>()); + float _theta = ur(r); + float _phi = ur(r); + T theta = truncate_to_float(&_theta); + T phi = truncate_to_float(&_phi); + + T r1 = spherical_harmonic_r(n, m, theta, phi); + T r2 = spherical_harmonic_i(n, m, theta, phi); + return boost::math::make_tuple(n, m, theta, phi, r1, r2); +} + +int main(int argc, char*argv []) +{ + using namespace boost::math::tools; + + parameter_info<mp_t> arg1, arg2, arg3; + test_data<mp_t> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + if(0 == get_user_parameter_info(arg1, "n")) + return 1; + arg1.type |= dummy_param; + arg2.type |= dummy_param; + arg3 = arg2; + + data.insert(&spherical_harmonic_data<mp_t>, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=spherical_harmonic.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "spherical_harmonic.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, line.c_str()); + + return 0; +} + diff --git a/src/boost/libs/math/tools/tgamma_large_data.cpp b/src/boost/libs/math/tools/tgamma_large_data.cpp new file mode 100644 index 00000000..dbf6ef34 --- /dev/null +++ b/src/boost/libs/math/tools/tgamma_large_data.cpp @@ -0,0 +1,75 @@ +// Copyright John Maddock 2013. +// 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) + +//[special_data_example + +#include <boost/multiprecision/mpfr.hpp> +#include <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <boost/math/tools/tuple.hpp> +#include <fstream> + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; +using namespace boost::multiprecision; + +typedef number<mpfr_float_backend<1000> > mp_type; + + +boost::math::tuple<mp_type, mp_type, mp_type> generate(mp_type a) +{ + mp_type tg, lg; + mpfr_gamma(tg.backend().data(), a.backend().data(), GMP_RNDN); + mpfr_lngamma(lg.backend().data(), a.backend().data(), GMP_RNDN); + return boost::math::make_tuple(a, tg, lg); +} + +int cpp_main(int argc, char*argv []) +{ + parameter_info<mp_type> arg1, arg2; + test_data<mp_type> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + // + // User interface which prompts for + // range of input parameters: + // + if(0 == get_user_parameter_info(arg1, "a")) + return 1; + arg1.type |= dummy_param; + + data.insert(&generate, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + // + // Just need to write the results to a file: + // + std::cout << "Enter name of test data file [default=gamma.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "gamma.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(500); + write_code(ofs, data, line.c_str()); + + return 0; +} + +//] + diff --git a/src/boost/libs/math/tools/tgamma_ratio_data.cpp b/src/boost/libs/math/tools/tgamma_ratio_data.cpp new file mode 100644 index 00000000..3f4e6722 --- /dev/null +++ b/src/boost/libs/math/tools/tgamma_ratio_data.cpp @@ -0,0 +1,91 @@ +// (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 <boost/math/special_functions/gamma.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace std; + +boost::math::tuple<mp_t, mp_t> + tgamma_ratio(const mp_t& a, const mp_t& delta) +{ + if(delta > a) + throw std::domain_error(""); + mp_t tg = boost::math::tgamma(a); + mp_t r1 = tg / boost::math::tgamma(a + delta); + mp_t r2 = tg / boost::math::tgamma(a - delta); + if((r1 > (std::numeric_limits<float>::max)()) || (r2 > (std::numeric_limits<float>::max)())) + throw std::domain_error(""); + + return boost::math::make_tuple(r1, r2); +} + +mp_t tgamma_ratio2(const mp_t& a, const mp_t& b) +{ + return boost::math::tgamma(a) / boost::math::tgamma(b); +} + + +int main(int argc, char*argv []) +{ + parameter_info<mp_t> arg1, arg2; + test_data<mp_t> data; + + bool cont; + std::string line; + + if((argc >= 2) && (strcmp(argv[1], "--ratio") == 0)) + { + std::cout << "Welcome.\n" + "This program will generate spot tests for the function tgamma_ratio(a, b)\n\n"; + + do{ + if(0 == get_user_parameter_info(arg1, "a")) + return 1; + if(0 == get_user_parameter_info(arg2, "b")) + return 1; + data.insert(&tgamma_ratio2, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + } + else + { + std::cout << "Welcome.\n" + "This program will generate spot tests for the function tgamma_delta_ratio(a, delta)\n\n"; + + do{ + if(0 == get_user_parameter_info(arg1, "a")) + return 1; + if(0 == get_user_parameter_info(arg2, "delta")) + return 1; + data.insert(&tgamma_ratio, arg1, arg2); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + } + + std::cout << "Enter name of test data file [default=tgamma_ratio_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "tgamma_ratio_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "tgamma_ratio_data"); + + return 0; +} + + diff --git a/src/boost/libs/math/tools/trig_data.cpp b/src/boost/libs/math/tools/trig_data.cpp new file mode 100644 index 00000000..41233578 --- /dev/null +++ b/src/boost/libs/math/tools/trig_data.cpp @@ -0,0 +1,83 @@ +// (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 <boost/math/constants/constants.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace std; + +float external_f; +float force_truncate(const float* f) +{ + external_f = *f; + return external_f; +} + +float truncate_to_float(mp_t r) +{ + float f = boost::math::tools::real_cast<float>(r); + return force_truncate(&f); +} + +struct trig_data_generator +{ + boost::math::tuple<mp_t, mp_t> operator()(mp_t z) + { + return boost::math::make_tuple(sin(z * boost::math::constants::pi<mp_t>()), cos(z * boost::math::constants::pi<mp_t>())); + } +}; + + +int main(int argc, char*argv []) +{ + parameter_info<mp_t> arg1; + test_data<mp_t> data; + + bool cont; + std::string line; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the cos_pi and sin_pi functions:\n"; + + do{ + if(0 == get_user_parameter_info(arg1, "a")) + return 1; + data.insert(trig_data_generator(), arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=trig_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "trig_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "trig_data"); + + return 0; +} + +/* Output for asymptotic limits: + +Erf asymptotic limit for 24 bit numbers is 2.8 after approximately 6 terms. +Erfc asymptotic limit for 24 bit numbers is 4.12064 after approximately 17 terms. +Erf asymptotic limit for 53 bit numbers is 4.3 after approximately 11 terms. +Erfc asymptotic limit for 53 bit numbers is 6.19035 after approximately 29 terms. +Erf asymptotic limit for 64 bit numbers is 4.8 after approximately 12 terms. +Erfc asymptotic limit for 64 bit numbers is 7.06004 after approximately 29 terms. +Erf asymptotic limit for 106 bit numbers is 6.5 after approximately 14 terms. +Erfc asymptotic limit for 106 bit numbers is 11.6626 after approximately 29 terms. +Erf asymptotic limit for 113 bit numbers is 6.8 after approximately 14 terms. +Erfc asymptotic limit for 113 bit numbers is 12.6802 after approximately 29 terms. +*/ + diff --git a/src/boost/libs/math/tools/zeta_data.cpp b/src/boost/libs/math/tools/zeta_data.cpp new file mode 100644 index 00000000..55c87c97 --- /dev/null +++ b/src/boost/libs/math/tools/zeta_data.cpp @@ -0,0 +1,72 @@ +// Copyright John Maddock 2007. +// 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 <boost/math/special_functions/zeta.hpp> +#include <boost/math/constants/constants.hpp> +#include <fstream> +#include <boost/math/tools/test_data.hpp> +#include "mp_t.hpp" + +using namespace boost::math::tools; +using namespace std; + +struct zeta_data_generator +{ + mp_t operator()(mp_t z) + { + std::cout << z << " "; + mp_t result = boost::math::zeta(z); + std::cout << result << std::endl; + return result; + } +}; + +struct zeta_data_generator2 +{ + boost::math::tuple<mp_t, mp_t> operator()(mp_t z) + { + std::cout << -z << " "; + mp_t result = boost::math::zeta(-z); + std::cout << result << std::endl; + return boost::math::make_tuple(-z, result); + } +}; + + +int main(int argc, char*argv []) +{ + parameter_info<mp_t> arg1; + test_data<mp_t> data; + + bool cont; + std::string line; + + std::cout << "Welcome.\n" + "This program will generate spot tests for the zeta function:\n"; + + do{ + if(0 == get_user_parameter_info(arg1, "z")) + return 1; + arg1.type |= dummy_param; + data.insert(zeta_data_generator2(), arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + + std::cout << "Enter name of test data file [default=zeta_data.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "zeta_data.ipp"; + std::ofstream ofs(line.c_str()); + ofs << std::scientific << std::setprecision(40); + write_code(ofs, data, "zeta_data"); + + return 0; +} + |