1 //  Copyright John Maddock 2006.
2 //  Copyright Paul A. Bristow 2007
3 //  Use, modification and distribution are subject to the
4 //  Boost Software License, Version 1.0. (See accompanying file
5 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #include <pch_light.hpp>
8 #include "test_erf.hpp"
9 
10 //
11 // DESCRIPTION:
12 // ~~~~~~~~~~~~
13 //
14 // This file tests the functions erf, erfc, and the inverses
15 // erf_inv and erfc_inv.  There are two sets of tests, spot
16 // tests which compare our results with selected values computed
17 // using the online special function calculator at
18 // functions.wolfram.com, while the bulk of the accuracy tests
19 // use values generated with NTL::RR at 1000-bit precision
20 // and our generic versions of these functions.
21 //
22 // Note that when this file is first run on a new platform many of
23 // these tests will fail: the default accuracy is 1 epsilon which
24 // is too tight for most platforms.  In this situation you will
25 // need to cast a human eye over the error rates reported and make
26 // a judgement as to whether they are acceptable.  Either way please
27 // report the results to the Boost mailing list.  Acceptable rates of
28 // error are marked up below as a series of regular expressions that
29 // identify the compiler/stdlib/platform/data-type/test-data/test-function
30 // along with the maximum expected peek and RMS mean errors for that
31 // test.
32 //
33 
expected_results()34 void expected_results()
35 {
36    //
37    // Define the max and mean errors expected for
38    // various compilers and platforms.
39    //
40    const char* largest_type;
41 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
42    if(boost::math::policies::digits<double, boost::math::policies::policy<> >() == boost::math::policies::digits<long double, boost::math::policies::policy<> >())
43    {
44       largest_type = "(long\\s+)?double|real_concept";
45    }
46    else
47    {
48       largest_type = "long double|real_concept";
49    }
50 #else
51    largest_type = "(long\\s+)?double";
52 #endif
53    //
54    // On MacOS X erfc has much higher error levels than
55    // expected: given that the implementation is basically
56    // just a rational function evaluation combined with
57    // exponentiation, we conclude that exp and pow are less
58    // accurate on this platform, especially when the result
59    // is outside the range of a double.
60    //
61    add_expected_result(
62       ".*",                          // compiler
63       ".*",                          // stdlib
64       "Mac OS",                      // platform
65       largest_type,                  // test type(s)
66       "Erf Function:.*Large.*",      // test data group
67       "boost::math::erfc", 4300, 1300);  // test function
68    add_expected_result(
69       ".*",                          // compiler
70       ".*",                          // stdlib
71       "Mac OS",                      // platform
72       largest_type,                  // test type(s)
73       "Erf Function:.*",             // test data group
74       "boost::math::erfc", 40, 10);  // test function
75 
76    add_expected_result(
77       ".*",                          // compiler
78       ".*",                          // stdlib
79       ".*",                          // platform
80       "real_concept",                // test type(s)
81       "Erf Function:.*",             // test data group
82       "boost::math::erfc?", 20, 6);   // test function
83    add_expected_result(
84       ".*",                           // compiler
85       ".*",                           // stdlib
86       ".*",                           // platform
87       "real_concept",                 // test type(s)
88       "Inverse Erfc.*",               // test data group
89       "boost::math::erfc_inv", 80, 10);  // test function
90 
91 
92    //
93    // Catch all cases come last:
94    //
95    add_expected_result(
96       ".*",                          // compiler
97       ".*",                          // stdlib
98       ".*",                          // platform
99       ".*",                          // test type(s)
100       "Erf Function:.*",             // test data group
101       "boost::math::erfc?", 2, 2);   // test function
102    add_expected_result(
103       ".*aCC.*",                     // compiler
104       ".*",                          // stdlib
105       ".*",                          // platform
106       ".*",                          // test type(s)
107       "Inverse Erfc.*",               // test data group
108       "boost::math::erfc_inv", 80, 10);  // test function
109    add_expected_result(
110       ".*",                          // compiler
111       ".*",                          // stdlib
112       ".*",                          // platform
113       ".*",                          // test type(s)
114       "Inverse Erf.*",               // test data group
115       "boost::math::erfc?_inv", 18, 4);  // test function
116 
117    //
118    // Finish off by printing out the compiler/stdlib/platform names,
119    // we do this to make it easier to mark up expected error rates.
120    //
121    std::cout << "Tests run with " << BOOST_COMPILER << ", "
122       << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl;
123 }
124 
BOOST_AUTO_TEST_CASE(test_main)125 BOOST_AUTO_TEST_CASE( test_main )
126 {
127    BOOST_MATH_CONTROL_FP;
128    test_spots(0.0F, "float");
129    test_spots(0.0, "double");
130 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
131    test_spots(0.0L, "long double");
132 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
133    test_spots(boost::math::concepts::real_concept(0.1), "real_concept");
134 #endif
135 #endif
136 
137    expected_results();
138 
139    test_erf(0.1F, "float");
140    test_erf(0.1, "double");
141 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
142    test_erf(0.1L, "long double");
143 #ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS
144 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
145    test_erf(boost::math::concepts::real_concept(0.1), "real_concept");
146 #endif
147 #endif
148 #else
149    std::cout << "<note>The long double tests have been disabled on this platform "
150       "either because the long double overloads of the usual math functions are "
151       "not available at all, or because they are too inaccurate for these tests "
152       "to pass.</note>" << std::cout;
153 #endif
154 }
155 
156 /*
157 
158 Output:
159 
160 test_erf.cpp
161 Compiling manifest to resources...
162 Linking...
163 Embedding manifest...
164 Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\test_erf.exe"
165 Running 1 test case...
166 Testing basic sanity checks for type float
167 Testing basic sanity checks for type double
168 Testing basic sanity checks for type long double
169 Testing basic sanity checks for type real_concept
170 Tests run with Microsoft Visual C++ version 8.0, Dinkumware standard library version 405, Win32
171 Testing Erf Function: Small Values with type float
172 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173 boost::math::erf<float> Max = 0 RMS Mean=0
174 boost::math::erfc<float> Max = 0 RMS Mean=0
175 Testing Erf Function: Medium Values with type float
176 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
177 boost::math::erf<float> Max = 0 RMS Mean=0
178 boost::math::erfc<float> Max = 0 RMS Mean=0
179 Testing Erf Function: Large Values with type float
180 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
181 boost::math::erf<float> Max = 0 RMS Mean=0
182 boost::math::erfc<float> Max = 0 RMS Mean=0
183 Testing Inverse Erf Function with type float
184 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
185 boost::math::erf_inv<float> Max = 0 RMS Mean=0
186 Testing Inverse Erfc Function with type float
187 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
188 boost::math::erfc_inv<float> Max = 0 RMS Mean=0
189 Testing Erf Function: Small Values with type double
190 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
191 boost::math::erf<double> Max = 0 RMS Mean=0
192 boost::math::erfc<double> Max = 0.7857 RMS Mean=0.06415
193     worst case at row: 149
194     { 0.3343, 0.3636, 0.6364 }
195 Testing Erf Function: Medium Values with type double
196 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
197 boost::math::erf<double> Max = 0.9219 RMS Mean=0.1016
198     worst case at row: 273
199     { 0.5252, 0.5424, 0.4576 }
200 boost::math::erfc<double> Max = 1.08 RMS Mean=0.3224
201     worst case at row: 287
202     { 0.8461, 0.7685, 0.2315 }
203 Testing Erf Function: Large Values with type double
204 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
205 boost::math::erf<double> Max = 0 RMS Mean=0
206 boost::math::erfc<double> Max = 1.048 RMS Mean=0.2032
207     worst case at row: 50
208     { 20.96, 1, 4.182e-193 }
209 Testing Inverse Erf Function with type double
210 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
211 boost::math::erf_inv<double> Max = 1.124 RMS Mean=0.5082
212     worst case at row: 98
213     { 0.9881, 1.779 }
214 Testing Inverse Erfc Function with type double
215 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
216 boost::math::erfc_inv<double> Max = 1.124 RMS Mean=0.5006
217     worst case at row: 98
218     { 1.988, -1.779 }
219 Testing Erf Function: Small Values with type long double
220 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
221 boost::math::erf<long double> Max = 0 RMS Mean=0
222 boost::math::erfc<long double> Max = 0.7857 RMS Mean=0.06415
223     worst case at row: 149
224     { 0.3343, 0.3636, 0.6364 }
225 Testing Erf Function: Medium Values with type long double
226 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
227 boost::math::erf<long double> Max = 0.9219 RMS Mean=0.1016
228     worst case at row: 273
229     { 0.5252, 0.5424, 0.4576 }
230 boost::math::erfc<long double> Max = 1.08 RMS Mean=0.3224
231     worst case at row: 287
232     { 0.8461, 0.7685, 0.2315 }
233 Testing Erf Function: Large Values with type long double
234 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
235 boost::math::erf<long double> Max = 0 RMS Mean=0
236 boost::math::erfc<long double> Max = 1.048 RMS Mean=0.2032
237     worst case at row: 50
238     { 20.96, 1, 4.182e-193 }
239 Testing Inverse Erf Function with type long double
240 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
241 boost::math::erf_inv<long double> Max = 1.124 RMS Mean=0.5082
242     worst case at row: 98
243     { 0.9881, 1.779 }
244 Testing Inverse Erfc Function with type long double
245 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
246 boost::math::erfc_inv<long double> Max = 1.124 RMS Mean=0.5006
247     worst case at row: 98
248     { 1.988, -1.779 }
249 Testing Erf Function: Small Values with type real_concept
250 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
251 boost::math::erf<real_concept> Max = 1.271 RMS Mean=0.5381
252     worst case at row: 144
253     { 0.0109, 0.0123, 0.9877 }
254 boost::math::erfc<real_concept> Max = 0.7857 RMS Mean=0.07777
255     worst case at row: 149
256     { 0.3343, 0.3636, 0.6364 }
257 Testing Erf Function: Medium Values with type real_concept
258 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
259 boost::math::erf<real_concept> Max = 22.5 RMS Mean=4.224
260     worst case at row: 233
261     { -0.7852, -0.7332, 1.733 }
262 Peak error greater than expected value of 20
263 i:/boost-sandbox/math_toolkit/libs/math/test/handle_test_result.hpp(146): error in "test_main_caller( argc, argv )": check bounds.first >= max_error_found failed
264 boost::math::erfc<real_concept> Max = 97.77 RMS Mean=8.373
265     worst case at row: 289
266     { 0.9849, 0.8363, 0.1637 }
267 Peak error greater than expected value of 20
268 i:/boost-sandbox/math_toolkit/libs/math/test/handle_test_result.hpp(146): error in "test_main_caller( argc, argv )": check bounds.first >= max_error_found failed
269 Mean error greater than expected value of 6
270 i:/boost-sandbox/math_toolkit/libs/math/test/handle_test_result.hpp(151): error in "test_main_caller( argc, argv )": check bounds.second >= mean_error_found failed
271 Testing Erf Function: Large Values with type real_concept
272 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
273 boost::math::erf<real_concept> Max = 0 RMS Mean=0
274 boost::math::erfc<real_concept> Max = 1.395 RMS Mean=0.2908
275     worst case at row: 11
276     { 10.99, 1, 1.87e-054 }
277 Testing Inverse Erf Function with type real_concept
278 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
279 boost::math::erf_inv<real_concept> Max = 1.124 RMS Mean=0.5082
280     worst case at row: 98
281     { 0.9881, 1.779 }
282 Testing Inverse Erfc Function with type real_concept
283 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
284 boost::math::erfc_inv<real_concept> Max = 1.124 RMS Mean=0.5006
285     worst case at row: 98
286     { 1.988, -1.779 }
287 Test suite "Test Program" failed with:
288   181 assertions out of 184 passed
289   3 assertions out of 184 failed
290   1 test case out of 1 failed
291   Test case "test_main_caller( argc, argv )" failed with:
292     181 assertions out of 184 passed
293     3 assertions out of 184 failed
294 Build Time 0:15
295 
296 */
297