1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 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
#define BOOST_MATH_USE_MPFR
#include "mp_t.hpp"
#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 <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;
}
|