1
// (C) Copyright John Maddock 2006.
2
// Use, modification and distribution are subject to the
3
// Boost Software License, Version 1.0. (See accompanying file
4
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
#include <boost/math/bindings/rr.hpp>
7
#include <boost/test/included/test_exec_monitor.hpp>
8
#include <boost/math/special_functions/gamma.hpp>
9
#include <boost/math/special_functions/erf.hpp> // for inverses
10
#include <boost/math/constants/constants.hpp>
11
#include <boost/math/tools/test.hpp>
14
#include <boost/math/tools/test_data.hpp>
16
using namespace boost::math::tools;
20
float force_truncate(const float* f)
26
float truncate_to_float(boost::math::ntl::RR r)
28
float f = boost::math::tools::real_cast<float>(r);
29
return force_truncate(&f);
32
struct erf_data_generator
34
boost::math::tuple<boost::math::ntl::RR, boost::math::ntl::RR> operator()(boost::math::ntl::RR z)
36
// very naively calculate spots using the gamma function at high precision:
43
boost::math::ntl::RR g1, g2;
44
g1 = boost::math::tgamma_lower(boost::math::ntl::RR(0.5), z * z);
45
g1 /= sqrt(boost::math::constants::pi<boost::math::ntl::RR>());
54
g2 = boost::math::tgamma(boost::math::ntl::RR(0.5), z * z);
55
g2 /= sqrt(boost::math::constants::pi<boost::math::ntl::RR>());
59
return boost::math::make_tuple(g1, g2);
63
double double_factorial(int N)
74
void asymptotic_limit(int Bits)
77
// The following block of code estimates how large z has
78
// to be before we can use the asymptotic expansion for
79
// erf/erfc and still get convergence: the series becomes
80
// divergent eventually so we have to be careful!
82
double result = (std::numeric_limits<double>::max)();
84
for(int n = 1; n < 15; ++n)
86
double lim = (Bits-n) * log(2.0) - log(sqrt(3.14)) + log(double_factorial(2*n+1));
88
while(x*x + (2*n+1)*log(x) <= lim)
97
std::cout << "Erf asymptotic limit for "
98
<< Bits << " bit numbers is "
99
<< result << " after approximately "
100
<< terms << " terms." << std::endl;
102
result = (std::numeric_limits<double>::max)();
104
for(int n = 1; n < 30; ++n)
106
double x = pow(double_factorial(2*n+1)/pow(2.0, n-Bits), 1 / (2.0*n));
114
std::cout << "Erfc asymptotic limit for "
115
<< Bits << " bit numbers is "
116
<< result << " after approximately "
117
<< terms << " terms." << std::endl;
120
boost::math::tuple<boost::math::ntl::RR, boost::math::ntl::RR> erfc_inv(boost::math::ntl::RR r)
122
boost::math::ntl::RR x = exp(-r * r);
123
x = NTL::RoundToPrecision(x.value(), 64);
124
std::cout << x << " ";
125
boost::math::ntl::RR result = boost::math::erfc_inv(x);
126
std::cout << result << std::endl;
127
return boost::math::make_tuple(x, result);
131
int test_main(int argc, char*argv [])
133
boost::math::ntl::RR::SetPrecision(1000);
134
boost::math::ntl::RR::SetOutputPrecision(40);
136
parameter_info<boost::math::ntl::RR> arg1;
137
test_data<boost::math::ntl::RR> data;
144
if(strcmp(argv[1], "--limits") == 0)
146
asymptotic_limit(24);
147
asymptotic_limit(53);
148
asymptotic_limit(64);
149
asymptotic_limit(106);
150
asymptotic_limit(113);
153
else if(strcmp(argv[1], "--erf_inv") == 0)
155
boost::math::ntl::RR (*f)(boost::math::ntl::RR);
156
f = boost::math::erf_inv;
157
std::cout << "Welcome.\n"
158
"This program will generate spot tests for the inverse erf function:\n";
159
std::cout << "Enter the number of data points: ";
162
data.insert(f, make_random_param(boost::math::ntl::RR(-1), boost::math::ntl::RR(1), points));
164
else if(strcmp(argv[1], "--erfc_inv") == 0)
166
boost::math::tuple<boost::math::ntl::RR, boost::math::ntl::RR> (*f)(boost::math::ntl::RR);
168
std::cout << "Welcome.\n"
169
"This program will generate spot tests for the inverse erfc function:\n";
170
std::cout << "Enter the maximum *result* expected from erfc_inv: ";
173
std::cout << "Enter the number of data points: ";
176
parameter_info<boost::math::ntl::RR> arg = make_random_param(boost::math::ntl::RR(0), boost::math::ntl::RR(max_val), points);
177
arg.type |= dummy_param;
183
std::cout << "Welcome.\n"
184
"This program will generate spot tests for the erf and erfc functions:\n"
185
" erf(z) and erfc(z)\n\n";
188
if(0 == get_user_parameter_info(arg1, "a"))
190
data.insert(erf_data_generator(), arg1);
192
std::cout << "Any more data [y/n]?";
193
std::getline(std::cin, line);
194
boost::algorithm::trim(line);
195
cont = (line == "y");
199
std::cout << "Enter name of test data file [default=erf_data.ipp]";
200
std::getline(std::cin, line);
201
boost::algorithm::trim(line);
203
line = "erf_data.ipp";
204
std::ofstream ofs(line.c_str());
205
write_code(ofs, data, "erf_data");
210
/* Output for asymptotic limits:
212
Erf asymptotic limit for 24 bit numbers is 2.8 after approximately 6 terms.
213
Erfc asymptotic limit for 24 bit numbers is 4.12064 after approximately 17 terms.
214
Erf asymptotic limit for 53 bit numbers is 4.3 after approximately 11 terms.
215
Erfc asymptotic limit for 53 bit numbers is 6.19035 after approximately 29 terms.
216
Erf asymptotic limit for 64 bit numbers is 4.8 after approximately 12 terms.
217
Erfc asymptotic limit for 64 bit numbers is 7.06004 after approximately 29 terms.
218
Erf asymptotic limit for 106 bit numbers is 6.5 after approximately 14 terms.
219
Erfc asymptotic limit for 106 bit numbers is 11.6626 after approximately 29 terms.
220
Erf asymptotic limit for 113 bit numbers is 6.8 after approximately 14 terms.
221
Erfc asymptotic limit for 113 bit numbers is 12.6802 after approximately 29 terms.