1 // test_nc_chi_squared.cpp
2
3 // Copyright John Maddock 2008.
4
5 // Use, modification and distribution are subject to the
6 // Boost Software License, Version 1.0.
7 // (See accompanying file LICENSE_1_0.txt
8 // or copy at http://www.boost.org/LICENSE_1_0.txt)
9
10 #include <pch.hpp>
11
12 #ifdef _MSC_VER
13 #pragma warning (disable:4127 4512)
14 #endif
15
16 #if !defined(TEST_FLOAT) && !defined(TEST_DOUBLE) && !defined(TEST_LDOUBLE) && !defined(TEST_REAL_CONCEPT)
17 # define TEST_FLOAT
18 # define TEST_DOUBLE
19 # define TEST_LDOUBLE
20 # define TEST_REAL_CONCEPT
21 #endif
22
23 #include <boost/math/concepts/real_concept.hpp> // for real_concept
24 #include <boost/math/distributions/non_central_chi_squared.hpp> // for chi_squared_distribution
25 #include <boost/math/special_functions/cbrt.hpp> // for chi_squared_distribution
26 #define BOOST_TEST_MAIN
27 #include <boost/test/unit_test.hpp> // for test_main
28 #include <boost/test/results_collector.hpp>
29 #include <boost/test/unit_test.hpp>
30 #include <boost/test/floating_point_comparison.hpp> // for BOOST_CHECK_CLOSE
31 #include "test_out_of_range.hpp"
32
33 #include "functor.hpp"
34 #include "handle_test_result.hpp"
35 #include "test_nccs_hooks.hpp"
36 #include "table_type.hpp"
37
38 #include <iostream>
39 #include <iomanip>
40 using std::cout;
41 using std::endl;
42 #include <limits>
43 using std::numeric_limits;
44
45 #define BOOST_CHECK_CLOSE_EX(a, b, prec, i) \
46 {\
47 unsigned int failures = boost::unit_test::results_collector.results( boost::unit_test::framework::current_test_case().p_id ).p_assertions_failed;\
48 BOOST_CHECK_CLOSE(a, b, prec); \
49 if(failures != boost::unit_test::results_collector.results( boost::unit_test::framework::current_test_case().p_id ).p_assertions_failed)\
50 {\
51 std::cerr << "Failure was at row " << i << std::endl;\
52 std::cerr << std::setprecision(35); \
53 std::cerr << "{ " << data[i][0] << " , " << data[i][1] << " , " << data[i][2];\
54 std::cerr << " , " << data[i][3] << " , " << data[i][4] << " } " << std::endl;\
55 }\
56 }
57
58 #define BOOST_CHECK_EX(a, i) \
59 {\
60 unsigned int failures = boost::unit_test::results_collector.results( boost::unit_test::framework::current_test_case().p_id ).p_assertions_failed;\
61 BOOST_CHECK(a); \
62 if(failures != boost::unit_test::results_collector.results( boost::unit_test::framework::current_test_case().p_id ).p_assertions_failed)\
63 {\
64 std::cerr << "Failure was at row " << i << std::endl;\
65 std::cerr << std::setprecision(35); \
66 std::cerr << "{ " << data[i][0] << " , " << data[i][1] << " , " << data[i][2];\
67 std::cerr << " , " << data[i][3] << " , " << data[i][4] << " } " << std::endl;\
68 }\
69 }
70
expected_results()71 void expected_results()
72 {
73 //
74 // Define the max and mean errors expected for
75 // various compilers and platforms.
76 //
77 const char* largest_type;
78 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
79 if(boost::math::policies::digits<double, boost::math::policies::policy<> >() == boost::math::policies::digits<long double, boost::math::policies::policy<> >())
80 {
81 largest_type = "(long\\s+)?double|real_concept";
82 }
83 else
84 {
85 largest_type = "long double|real_concept";
86 }
87 #else
88 largest_type = "(long\\s+)?double|real_concept";
89 #endif
90
91 add_expected_result(
92 "[^|]*", // compiler
93 "[^|]*", // stdlib
94 "Mac OS", // platform
95 largest_type, // test type(s)
96 "[^|]*medium[^|]*", // test data group
97 "[^|]*", 550, 100); // test function
98 //
99 // Catch all cases come last:
100 //
101 add_expected_result(
102 "[^|]*", // compiler
103 "[^|]*", // stdlib
104 "[^|]*", // platform
105 largest_type, // test type(s)
106 "[^|]*medium[^|]*", // test data group
107 "[^|]*", 350, 100); // test function
108 add_expected_result(
109 "[^|]*", // compiler
110 "[^|]*", // stdlib
111 "[^|]*", // platform
112 largest_type, // test type(s)
113 "[^|]*large[^|]*", // test data group
114 "[^|]*", 17000, 3000); // test function
115
116 //
117 // Allow some long double error to creep into
118 // the double results:
119 //
120 add_expected_result(
121 "[^|]*", // compiler
122 "[^|]*", // stdlib
123 "[^|]*", // platform
124 "double", // test type(s)
125 "[^|]*", // test data group
126 "[^|]*", 3, 2); // test function
127
128 //
129 // Finish off by printing out the compiler/stdlib/platform names,
130 // we do this to make it easier to mark up expected error rates.
131 //
132 std::cout << "Tests run with " << BOOST_COMPILER << ", "
133 << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl;
134 }
135
136 template <class RealType>
naive_pdf(RealType v,RealType lam,RealType x)137 RealType naive_pdf(RealType v, RealType lam, RealType x)
138 {
139 // Formula direct from
140 // http://mathworld.wolfram.com/NoncentralChi-SquaredDistribution.html
141 // with no simplification:
142 RealType sum, term, prefix(1);
143 RealType eps = boost::math::tools::epsilon<RealType>();
144 term = sum = pdf(boost::math::chi_squared_distribution<RealType>(v), x);
145 for(int i = 1;; ++i)
146 {
147 prefix *= lam / (2 * i);
148 term = prefix * pdf(boost::math::chi_squared_distribution<RealType>(v + 2 * i), x);
149 sum += term;
150 if(term / sum < eps)
151 break;
152 }
153 return sum * exp(-lam/2);
154 }
155
156 template <class RealType>
test_spot(RealType df,RealType ncp,RealType cs,RealType P,RealType Q,RealType tol)157 void test_spot(
158 RealType df, // Degrees of freedom
159 RealType ncp, // non-centrality param
160 RealType cs, // Chi Square statistic
161 RealType P, // CDF
162 RealType Q, // Complement of CDF
163 RealType tol) // Test tolerance
164 {
165 boost::math::non_central_chi_squared_distribution<RealType> dist(df, ncp);
166 BOOST_CHECK_CLOSE(
167 cdf(dist, cs), P, tol);
168 try{
169 BOOST_CHECK_CLOSE(
170 pdf(dist, cs), naive_pdf(dist.degrees_of_freedom(), ncp, cs), tol * 150);
171 }
172 catch(const std::overflow_error&)
173 {}
174 if((P < 0.99) && (Q < 0.99))
175 {
176 //
177 // We can only check this if P is not too close to 1,
178 // so that we can guarentee Q is reasonably free of error:
179 //
180 BOOST_CHECK_CLOSE(
181 cdf(complement(dist, cs)), Q, tol);
182 BOOST_CHECK_CLOSE(
183 quantile(dist, P), cs, tol * 10);
184 BOOST_CHECK_CLOSE(
185 quantile(complement(dist, Q)), cs, tol * 10);
186 BOOST_CHECK_CLOSE(
187 dist.find_degrees_of_freedom(ncp, cs, P), df, tol * 10);
188 BOOST_CHECK_CLOSE(
189 dist.find_degrees_of_freedom(boost::math::complement(ncp, cs, Q)), df, tol * 10);
190 BOOST_CHECK_CLOSE(
191 dist.find_non_centrality(df, cs, P), ncp, tol * 10);
192 BOOST_CHECK_CLOSE(
193 dist.find_non_centrality(boost::math::complement(df, cs, Q)), ncp, tol * 10);
194 }
195 }
196
197 template <class RealType> // Any floating-point type RealType.
test_spots(RealType)198 void test_spots(RealType)
199 {
200 RealType tolerance = (std::max)(
201 boost::math::tools::epsilon<RealType>(),
202 (RealType)boost::math::tools::epsilon<double>() * 5) * 150;
203 //
204 // At float precision we need to up the tolerance, since
205 // the input values are rounded off to inexact quantities
206 // the results get thrown off by a noticeable amount.
207 //
208 if(boost::math::tools::digits<RealType>() < 50)
209 tolerance *= 50;
210 if(boost::is_floating_point<RealType>::value != 1)
211 tolerance *= 20; // real_concept special functions are less accurate
212
213 cout << "Tolerance = " << tolerance << "%." << endl;
214
215 using boost::math::chi_squared_distribution;
216 using ::boost::math::chi_squared;
217 using ::boost::math::cdf;
218 using ::boost::math::pdf;
219 //
220 // Test against the data from Table 6 of:
221 //
222 // "Self-Validating Computations of Probabilities for Selected
223 // Central and Noncentral Univariate Probability Functions."
224 // Morgan C. Wang; William J. Kennedy
225 // Journal of the American Statistical Association,
226 // Vol. 89, No. 427. (Sep., 1994), pp. 878-887.
227 //
228 test_spot(
229 static_cast<RealType>(1), // degrees of freedom
230 static_cast<RealType>(6), // non centrality
231 static_cast<RealType>(0.00393), // Chi Squared statistic
232 static_cast<RealType>(0.2498463724258039e-2), // Probability of result (CDF), P
233 static_cast<RealType>(1-0.2498463724258039e-2), // Q = 1 - P
234 tolerance);
235 test_spot(
236 static_cast<RealType>(5), // degrees of freedom
237 static_cast<RealType>(1), // non centrality
238 static_cast<RealType>(9.23636), // Chi Squared statistic
239 static_cast<RealType>(0.8272918751175548), // Probability of result (CDF), P
240 static_cast<RealType>(1-0.8272918751175548), // Q = 1 - P
241 tolerance);
242 test_spot(
243 static_cast<RealType>(11), // degrees of freedom
244 static_cast<RealType>(21), // non centrality
245 static_cast<RealType>(24.72497), // Chi Squared statistic
246 static_cast<RealType>(0.2539481822183126), // Probability of result (CDF), P
247 static_cast<RealType>(1-0.2539481822183126), // Q = 1 - P
248 tolerance);
249 test_spot(
250 static_cast<RealType>(31), // degrees of freedom
251 static_cast<RealType>(6), // non centrality
252 static_cast<RealType>(44.98534), // Chi Squared statistic
253 static_cast<RealType>(0.8125198785064969), // Probability of result (CDF), P
254 static_cast<RealType>(1-0.8125198785064969), // Q = 1 - P
255 tolerance);
256 test_spot(
257 static_cast<RealType>(51), // degrees of freedom
258 static_cast<RealType>(1), // non centrality
259 static_cast<RealType>(38.56038), // Chi Squared statistic
260 static_cast<RealType>(0.8519497361859118e-1), // Probability of result (CDF), P
261 static_cast<RealType>(1-0.8519497361859118e-1), // Q = 1 - P
262 tolerance * 2);
263 test_spot(
264 static_cast<RealType>(100), // degrees of freedom
265 static_cast<RealType>(16), // non centrality
266 static_cast<RealType>(82.35814), // Chi Squared statistic
267 static_cast<RealType>(0.1184348822747824e-1), // Probability of result (CDF), P
268 static_cast<RealType>(1-0.1184348822747824e-1), // Q = 1 - P
269 tolerance);
270 test_spot(
271 static_cast<RealType>(300), // degrees of freedom
272 static_cast<RealType>(16), // non centrality
273 static_cast<RealType>(331.78852), // Chi Squared statistic
274 static_cast<RealType>(0.7355956710306709), // Probability of result (CDF), P
275 static_cast<RealType>(1-0.7355956710306709), // Q = 1 - P
276 tolerance);
277 test_spot(
278 static_cast<RealType>(500), // degrees of freedom
279 static_cast<RealType>(21), // non centrality
280 static_cast<RealType>(459.92612), // Chi Squared statistic
281 static_cast<RealType>(0.2797023600800060e-1), // Probability of result (CDF), P
282 static_cast<RealType>(1-0.2797023600800060e-1), // Q = 1 - P
283 tolerance);
284 test_spot(
285 static_cast<RealType>(1), // degrees of freedom
286 static_cast<RealType>(1), // non centrality
287 static_cast<RealType>(0.00016), // Chi Squared statistic
288 static_cast<RealType>(0.6121428929881423e-2), // Probability of result (CDF), P
289 static_cast<RealType>(1-0.6121428929881423e-2), // Q = 1 - P
290 tolerance);
291 test_spot(
292 static_cast<RealType>(1), // degrees of freedom
293 static_cast<RealType>(1), // non centrality
294 static_cast<RealType>(0.00393), // Chi Squared statistic
295 static_cast<RealType>(0.3033814229753780e-1), // Probability of result (CDF), P
296 static_cast<RealType>(1-0.3033814229753780e-1), // Q = 1 - P
297 tolerance);
298
299 RealType tol2 = boost::math::tools::epsilon<RealType>() * 5 * 100; // 5 eps as a percentage
300 boost::math::non_central_chi_squared_distribution<RealType> dist(static_cast<RealType>(8), static_cast<RealType>(12));
301 RealType x = 7;
302 using namespace std; // ADL of std names.
303 // mean:
304 BOOST_CHECK_CLOSE(
305 mean(dist)
306 , static_cast<RealType>(8+12), tol2);
307 // variance:
308 BOOST_CHECK_CLOSE(
309 variance(dist)
310 , static_cast<RealType>(64), tol2);
311 // std deviation:
312 BOOST_CHECK_CLOSE(
313 standard_deviation(dist)
314 , static_cast<RealType>(8), tol2);
315 // hazard:
316 BOOST_CHECK_CLOSE(
317 hazard(dist, x)
318 , pdf(dist, x) / cdf(complement(dist, x)), tol2);
319 // cumulative hazard:
320 BOOST_CHECK_CLOSE(
321 chf(dist, x)
322 , -log(cdf(complement(dist, x))), tol2);
323 // coefficient_of_variation:
324 BOOST_CHECK_CLOSE(
325 coefficient_of_variation(dist)
326 , standard_deviation(dist) / mean(dist), tol2);
327 // mode:
328 BOOST_CHECK_CLOSE(
329 mode(dist)
330 , static_cast<RealType>(17.184201184730857030170788677340294070728990862663L), sqrt(tolerance * 500));
331 BOOST_CHECK_CLOSE(
332 median(dist),
333 quantile(
334 boost::math::non_central_chi_squared_distribution<RealType>(
335 static_cast<RealType>(8),
336 static_cast<RealType>(12)),
337 static_cast<RealType>(0.5)), static_cast<RealType>(tol2));
338 // skewness:
339 BOOST_CHECK_CLOSE(
340 skewness(dist)
341 , static_cast<RealType>(0.6875), tol2);
342 // kurtosis:
343 BOOST_CHECK_CLOSE(
344 kurtosis(dist)
345 , static_cast<RealType>(3.65625), tol2);
346 // kurtosis excess:
347 BOOST_CHECK_CLOSE(
348 kurtosis_excess(dist)
349 , static_cast<RealType>(0.65625), tol2);
350
351 // Error handling checks:
352 check_out_of_range<boost::math::non_central_chi_squared_distribution<RealType> >(1, 1);
353 BOOST_CHECK_THROW(pdf(boost::math::non_central_chi_squared_distribution<RealType>(0, 1), 0), std::domain_error);
354 BOOST_CHECK_THROW(pdf(boost::math::non_central_chi_squared_distribution<RealType>(-1, 1), 0), std::domain_error);
355 BOOST_CHECK_THROW(pdf(boost::math::non_central_chi_squared_distribution<RealType>(1, -1), 0), std::domain_error);
356 BOOST_CHECK_THROW(quantile(boost::math::non_central_chi_squared_distribution<RealType>(1, 1), -1), std::domain_error);
357 BOOST_CHECK_THROW(quantile(boost::math::non_central_chi_squared_distribution<RealType>(1, 1), 2), std::domain_error);
358 } // template <class RealType>void test_spots(RealType)
359
360 template <class T>
nccs_cdf(T df,T nc,T x)361 T nccs_cdf(T df, T nc, T x)
362 {
363 return cdf(boost::math::non_central_chi_squared_distribution<T>(df, nc), x);
364 }
365
366 template <class T>
nccs_ccdf(T df,T nc,T x)367 T nccs_ccdf(T df, T nc, T x)
368 {
369 return cdf(complement(boost::math::non_central_chi_squared_distribution<T>(df, nc), x));
370 }
371
372 template <typename Real, typename T>
do_test_nc_chi_squared(T & data,const char * type_name,const char * test)373 void do_test_nc_chi_squared(T& data, const char* type_name, const char* test)
374 {
375 typedef typename T::value_type row_type;
376 typedef Real value_type;
377
378 std::cout << "Testing: " << test << std::endl;
379
380 value_type (*fp1)(value_type, value_type, value_type) = nccs_cdf;
381 boost::math::tools::test_result<value_type> result;
382
383 result = boost::math::tools::test_hetero<Real>(
384 data,
385 bind_func<Real>(fp1, 0, 1, 2),
386 extract_result<Real>(3));
387 handle_test_result(result, data[result.worst()], result.worst(),
388 type_name, "CDF", test);
389
390 fp1 = nccs_ccdf;
391 result = boost::math::tools::test_hetero<Real>(
392 data,
393 bind_func<Real>(fp1, 0, 1, 2),
394 extract_result<Real>(4));
395 handle_test_result(result, data[result.worst()], result.worst(),
396 type_name, "CCDF", test);
397
398 #ifdef TEST_OTHER
399 fp1 = other::nccs_cdf;
400 result = boost::math::tools::test_hetero<Real>(
401 data,
402 bind_func<Real>(fp1, 0, 1, 2),
403 extract_result<Real>(3));
404 handle_test_result(result, data[result.worst()], result.worst(),
405 type_name, "other::CDF", test);
406 #endif
407
408 std::cout << std::endl;
409
410 }
411
412 template <typename Real, typename T>
quantile_sanity_check(T & data,const char * type_name,const char * test)413 void quantile_sanity_check(T& data, const char* type_name, const char* test)
414 {
415 typedef typename T::value_type row_type;
416 typedef Real value_type;
417
418 //
419 // Tests with type real_concept take rather too long to run, so
420 // for now we'll disable them:
421 //
422 if(!boost::is_floating_point<value_type>::value)
423 return;
424
425 std::cout << "Testing: " << type_name << " quantile sanity check, with tests " << test << std::endl;
426
427 //
428 // These sanity checks test for a round trip accuracy of one half
429 // of the bits in T, unless T is type float, in which case we check
430 // for just one decimal digit. The problem here is the sensitivity
431 // of the functions, not their accuracy. This test data was generated
432 // for the forward functions, which means that when it is used as
433 // the input to the inverses then it is necessarily inexact. This rounding
434 // of the input is what makes the data unsuitable for use as an accuracy check,
435 // and also demonstrates that you can't in general round-trip these functions.
436 // It is however a useful sanity check.
437 //
438 value_type precision = static_cast<value_type>(ldexp(1.0, 1-boost::math::policies::digits<value_type, boost::math::policies::policy<> >()/2)) * 100;
439 if(boost::math::policies::digits<value_type, boost::math::policies::policy<> >() < 50)
440 precision = 1; // 1% or two decimal digits, all we can hope for when the input is truncated to float
441
442 for(unsigned i = 0; i < data.size(); ++i)
443 {
444 if(Real(data[i][3]) == 0)
445 {
446 BOOST_CHECK(0 == quantile(boost::math::non_central_chi_squared_distribution<value_type>(data[i][0], data[i][1]), data[i][3]));
447 }
448 else if(data[i][3] < 0.9999f)
449 {
450 value_type p = quantile(boost::math::non_central_chi_squared_distribution<value_type>(data[i][0], data[i][1]), data[i][3]);
451 value_type pt = data[i][2];
452 BOOST_CHECK_CLOSE_EX(pt, p, precision, i);
453 }
454 if(data[i][4] == 0)
455 {
456 BOOST_CHECK(0 == quantile(complement(boost::math::non_central_chi_squared_distribution<value_type>(data[i][0], data[i][1]), data[i][3])));
457 }
458 else if(data[i][4] < 0.9999f)
459 {
460 value_type p = quantile(complement(boost::math::non_central_chi_squared_distribution<value_type>(data[i][0], data[i][1]), data[i][4]));
461 value_type pt = data[i][2];
462 BOOST_CHECK_CLOSE_EX(pt, p, precision, i);
463 }
464 if(boost::math::tools::digits<value_type>() > 50)
465 {
466 //
467 // Sanity check mode, the accuracy of
468 // the mode is at *best* the square root of the accuracy of the PDF:
469 //
470 try{
471 value_type m = mode(boost::math::non_central_chi_squared_distribution<value_type>(data[i][0], data[i][1]));
472 value_type p = pdf(boost::math::non_central_chi_squared_distribution<value_type>(data[i][0], data[i][1]), m);
473 BOOST_CHECK_EX(pdf(boost::math::non_central_chi_squared_distribution<value_type>(data[i][0], data[i][1]), m * (1 + sqrt(precision) * 50)) <= p, i);
474 BOOST_CHECK_EX(pdf(boost::math::non_central_chi_squared_distribution<value_type>(data[i][0], data[i][1]), m * (1 - sqrt(precision)) * 50) <= p, i);
475 }
476 catch(const boost::math::evaluation_error& ) {}
477 //
478 // Sanity check degrees-of-freedom finder, don't bother at float
479 // precision though as there's not enough data in the probability
480 // values to get back to the correct degrees of freedom or
481 // non-cenrality parameter:
482 //
483 try{
484 if((data[i][3] < 0.99) && (data[i][3] != 0))
485 {
486 BOOST_CHECK_CLOSE_EX(
487 boost::math::non_central_chi_squared_distribution<value_type>::find_degrees_of_freedom(data[i][1], data[i][2], data[i][3]),
488 data[i][0], precision, i);
489 BOOST_CHECK_CLOSE_EX(
490 boost::math::non_central_chi_squared_distribution<value_type>::find_non_centrality(data[i][0], data[i][2], data[i][3]),
491 data[i][1], precision, i);
492 }
493 if((data[i][4] < 0.99) && (data[i][4] != 0))
494 {
495 BOOST_CHECK_CLOSE_EX(
496 boost::math::non_central_chi_squared_distribution<value_type>::find_degrees_of_freedom(boost::math::complement(data[i][1], data[i][2], data[i][4])),
497 data[i][0], precision, i);
498 BOOST_CHECK_CLOSE_EX(
499 boost::math::non_central_chi_squared_distribution<value_type>::find_non_centrality(boost::math::complement(data[i][0], data[i][2], data[i][4])),
500 data[i][1], precision, i);
501 }
502 }
503 catch(const std::exception& e)
504 {
505 BOOST_ERROR(e.what());
506 }
507 }
508 }
509 }
510
511 template <typename T>
test_accuracy(T,const char * type_name)512 void test_accuracy(T, const char* type_name)
513 {
514 #include "nccs.ipp"
515 do_test_nc_chi_squared<T>(nccs, type_name, "Non Central Chi Squared, medium parameters");
516 quantile_sanity_check<T>(nccs, type_name, "Non Central Chi Squared, medium parameters");
517
518 #include "nccs_big.ipp"
519 do_test_nc_chi_squared<T>(nccs_big, type_name, "Non Central Chi Squared, large parameters");
520 quantile_sanity_check<T>(nccs_big, type_name, "Non Central Chi Squared, large parameters");
521 }
522
BOOST_AUTO_TEST_CASE(test_main)523 BOOST_AUTO_TEST_CASE( test_main )
524 {
525 BOOST_MATH_CONTROL_FP;
526 // Basic sanity-check spot values.
527 expected_results();
528 // (Parameter value, arbitrarily zero, only communicates the floating point type).
529 #ifdef TEST_FLOAT
530 test_spots(0.0F); // Test float.
531 #endif
532 #ifdef TEST_DOUBLE
533 test_spots(0.0); // Test double.
534 #endif
535 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
536 #ifdef TEST_LDOUBLE
537 test_spots(0.0L); // Test long double.
538 #endif
539 #ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS
540 #ifdef TEST_REAL_CONCEPT
541 test_spots(boost::math::concepts::real_concept(0.)); // Test real concept.
542 #endif
543 #endif
544 #endif
545
546 #ifdef TEST_FLOAT
547 test_accuracy(0.0F, "float"); // Test float.
548 #endif
549 #ifdef TEST_DOUBLE
550 test_accuracy(0.0, "double"); // Test double.
551 #endif
552 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
553 #ifdef TEST_LDOUBLE
554 test_accuracy(0.0L, "long double"); // Test long double.
555 #endif
556 #ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS
557 #ifdef TEST_REAL_CONCEPT
558 test_accuracy(boost::math::concepts::real_concept(0.), "real_concept"); // Test real concept.
559 #endif
560 #endif
561 #endif
562
563 } // BOOST_AUTO_TEST_CASE( test_main )
564
565
566