• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright John Maddock 2006.
2 
3 // Use, modification and distribution are subject to the
4 // Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt
6 // or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 // test_rayleigh.cpp
9 
10 #ifdef _MSC_VER
11 #  pragma warning(disable: 4127) // conditional expression is constant.
12 #  pragma warning(disable: 4100) // unreferenced formal parameter.
13 #endif
14 
15 #include <boost/math/concepts/real_concept.hpp> // for real_concept
16 #include <boost/math/distributions/rayleigh.hpp>
17     using boost::math::rayleigh_distribution;
18 #include <boost/math/tools/test.hpp>
19 
20 #define BOOST_TEST_MAIN
21 #include <boost/test/unit_test.hpp> // Boost.Test
22 #include <boost/test/tools/floating_point_comparison.hpp>
23 #include "test_out_of_range.hpp"
24 
25 #include <iostream>
26    using std::cout;
27    using std::endl;
28    using std::setprecision;
29 
30 template <class RealType>
test_spot(RealType s,RealType x,RealType p,RealType q,RealType tolerance)31 void test_spot(RealType s, RealType x, RealType p, RealType q, RealType tolerance)
32 {
33    BOOST_CHECK_CLOSE(
34       ::boost::math::cdf(
35          rayleigh_distribution<RealType>(s),
36          x),
37          p,
38          tolerance); // %
39    BOOST_CHECK_CLOSE(
40       ::boost::math::cdf(
41          complement(rayleigh_distribution<RealType>(s),
42          x)),
43          q,
44          tolerance); // %
45    // Special extra tests for p and q near to unity.
46    if(p < 0.999)
47    {
48       BOOST_CHECK_CLOSE(
49          ::boost::math::quantile(
50             rayleigh_distribution<RealType>(s),
51             p),
52             x,
53             tolerance); // %
54    }
55    if(q < 0.999)
56    {
57       BOOST_CHECK_CLOSE(
58          ::boost::math::quantile(
59             complement(rayleigh_distribution<RealType>(s),
60             q)),
61             x,
62             tolerance); // %
63    }
64    if(std::numeric_limits<RealType>::has_infinity)
65    {
66       RealType inf = std::numeric_limits<RealType>::infinity();
67       BOOST_CHECK_EQUAL(pdf(rayleigh_distribution<RealType>(s), inf), 0);
68       BOOST_CHECK_EQUAL(cdf(rayleigh_distribution<RealType>(s), inf), 1);
69       BOOST_CHECK_EQUAL(cdf(complement(rayleigh_distribution<RealType>(s), inf)), 0);
70    }
71 } // void test_spot
72 
73 template <class RealType>
test_spots(RealType T)74 void test_spots(RealType T)
75 {
76    using namespace std; // ADL of std names.
77    // Basic sanity checks.
78    // 50 eps as a percentage, up to a maximum of double precision
79    // (that's the limit of our test data: obtained by punching
80    // numbers into a calculator).
81    RealType tolerance = (std::max)(
82       static_cast<RealType>(boost::math::tools::epsilon<double>()),
83       boost::math::tools::epsilon<RealType>());
84    tolerance *= 10 * 100; // 10 eps as a percent
85    cout << "Tolerance for type " << typeid(T).name()  << " is " << tolerance << " %" << endl;
86 
87   using namespace boost::math::constants;
88 
89    // Things that are errors:
90    rayleigh_distribution<RealType> dist(0.5);
91 
92    check_out_of_range<rayleigh_distribution<RealType> >(1);
93    BOOST_MATH_CHECK_THROW(
94        quantile(dist,
95        RealType(1.)), // quantile unity should overflow.
96        std::overflow_error);
97    BOOST_MATH_CHECK_THROW(
98        quantile(complement(dist,
99        RealType(0.))), // quantile complement zero should overflow.
100        std::overflow_error);
101    BOOST_MATH_CHECK_THROW(
102        pdf(dist, RealType(-1)), // Bad negative x.
103        std::domain_error);
104    BOOST_MATH_CHECK_THROW(
105        cdf(dist, RealType(-1)), // Bad negative x.
106        std::domain_error);
107    BOOST_MATH_CHECK_THROW(
108        cdf(rayleigh_distribution<RealType>(-1), // bad sigma < 0
109        RealType(1)),
110        std::domain_error);
111    BOOST_MATH_CHECK_THROW(
112        cdf(rayleigh_distribution<RealType>(0), // bad sigma == 0
113        RealType(1)),
114        std::domain_error);
115    BOOST_MATH_CHECK_THROW(
116        quantile(dist, RealType(-1)), // negative quantile probability.
117        std::domain_error);
118    BOOST_MATH_CHECK_THROW(
119        quantile(dist, RealType(2)), // > unity  quantile probability.
120        std::domain_error);
121 
122    test_spot(
123       static_cast<RealType>(1.L), // sigma
124       static_cast<RealType>(1.L), // x
125       static_cast<RealType>(1 - exp_minus_half<RealType>()), // p
126       static_cast<RealType>(exp_minus_half<RealType>()), // q
127       tolerance);
128 
129    test_spot(
130       static_cast<RealType>(0.5L), // sigma
131       static_cast<RealType>(0.5L), // x
132       static_cast<RealType>(1 - exp_minus_half<RealType>()), // p
133       static_cast<RealType>(exp_minus_half<RealType>()), //q
134       tolerance);
135 
136    test_spot(
137       static_cast<RealType>(3.L), // sigma
138       static_cast<RealType>(3.L), // x
139       static_cast<RealType>(1 - exp_minus_half<RealType>()), // p
140       static_cast<RealType>(exp_minus_half<RealType>()), //q
141       tolerance);
142 
143    BOOST_CHECK_CLOSE(
144       ::boost::math::pdf(
145          rayleigh_distribution<RealType>(1.L),
146          static_cast<RealType>(1.L)),              // x
147          static_cast<RealType>(exp_minus_half<RealType>()), // probability.
148          tolerance); // %
149    BOOST_CHECK_CLOSE(
150       ::boost::math::pdf(
151          rayleigh_distribution<RealType>(0.5L),
152          static_cast<RealType>(0.5L)),              // x
153          static_cast<RealType>(2 * exp_minus_half<RealType>()), // probability.
154          tolerance); // %
155    BOOST_CHECK_CLOSE(
156       ::boost::math::pdf(
157          rayleigh_distribution<RealType>(2.L),
158          static_cast<RealType>(2.L)),              // x
159          static_cast<RealType>(exp_minus_half<RealType>() /2),  // probability.
160          tolerance); // %
161 
162    BOOST_CHECK_CLOSE(
163       ::boost::math::mean(
164          rayleigh_distribution<RealType>(1.L)),
165          static_cast<RealType>(root_half_pi<RealType>()),
166          tolerance); // %
167    BOOST_CHECK_CLOSE(
168       ::boost::math::variance(
169          rayleigh_distribution<RealType>(root_two<RealType>())),
170          static_cast<RealType>(four_minus_pi<RealType>()),
171          tolerance * 100); // %
172 
173    BOOST_CHECK_CLOSE(
174       ::boost::math::mode(
175          rayleigh_distribution<RealType>(1.L)),
176          static_cast<RealType>(1.L),
177          tolerance); // %
178 
179    BOOST_CHECK_CLOSE(
180       ::boost::math::median(
181          rayleigh_distribution<RealType>(1.L)),
182          static_cast<RealType>(sqrt(log(4.L))),  // sigma * sqrt(log_four)
183          tolerance); // %
184 
185    BOOST_CHECK_CLOSE(
186       ::boost::math::skewness(
187          rayleigh_distribution<RealType>(1.L)),
188          static_cast<RealType>(2.L * root_pi<RealType>()) * (pi<RealType>() - 3) / (pow((4 - pi<RealType>()), static_cast<RealType>(1.5L))),
189          tolerance * 100); // %
190 
191    BOOST_CHECK_CLOSE(
192       ::boost::math::skewness(
193          rayleigh_distribution<RealType>(1.L)),
194          static_cast<RealType>(0.63111065781893713819189935154422777984404221106391L),
195          tolerance * 100); // %
196 
197    BOOST_CHECK_CLOSE(
198      ::boost::math::kurtosis_excess(
199      rayleigh_distribution<RealType>(1.L)),
200      -static_cast<RealType>(6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
201         ((4 - pi<RealType>()) * (4 - pi<RealType>())),
202         // static_cast<RealType>(0.2450893006876380628486604106197544154170667057995L),
203          tolerance * 1000); // %
204 
205    BOOST_CHECK_CLOSE(
206       ::boost::math::kurtosis(
207          rayleigh_distribution<RealType>(1.L)),
208          static_cast<RealType>(3.2450893006876380628486604106197544154170667057995L),
209          tolerance * 100); // %
210 
211 
212    BOOST_CHECK_CLOSE(
213       ::boost::math::kurtosis_excess(rayleigh_distribution<RealType>(2)),
214       ::boost::math::kurtosis(rayleigh_distribution<RealType>(2)) -3,
215          tolerance* 100); // %
216 
217 
218    RealType expected_entropy = 1 + log(boost::math::constants::root_two<RealType>()) + boost::math::constants::euler<RealType>()/2;
219    BOOST_CHECK_CLOSE(
220       ::boost::math::entropy(rayleigh_distribution<RealType>(2)),
221       expected_entropy,
222          tolerance* 100);
223    return;
224 
225 } // template <class RealType>void test_spots(RealType)
226 
BOOST_AUTO_TEST_CASE(test_main)227 BOOST_AUTO_TEST_CASE( test_main )
228 {
229   // Check that can generate rayleigh distribution using the two convenience methods:
230    boost::math::rayleigh ray1(1.); // Using typedef
231    rayleigh_distribution<> ray2(1.); // Using default RealType double.
232 
233   using namespace boost::math::constants;
234    // Basic sanity-check spot values.
235 
236   // Double only tests.
237    BOOST_CHECK_CLOSE_FRACTION(
238       ::boost::math::pdf(
239       rayleigh_distribution<double>(1.),
240       static_cast<double>(1)), // x
241       static_cast<double>(exp_minus_half<double>()), // p
242          1e-15); // %
243 
244    BOOST_CHECK_CLOSE_FRACTION(
245       ::boost::math::pdf(
246       rayleigh_distribution<double>(0.5),
247       static_cast<double>(0.5)), // x
248       static_cast<double>(2 * exp_minus_half<double>()), // p
249          1e-15); // %
250 
251    BOOST_CHECK_CLOSE_FRACTION(
252       ::boost::math::pdf(
253       rayleigh_distribution<double>(2.),
254       static_cast<double>(2)), // x
255       static_cast<double>(exp_minus_half<double>() /2 ), // p
256          1e-15); // %
257 
258    BOOST_CHECK_CLOSE_FRACTION(
259       ::boost::math::cdf(
260       rayleigh_distribution<double>(1.),
261       static_cast<double>(1)), // x
262       static_cast<double>(1- exp_minus_half<double>()), // p
263          1e-15); // %
264 
265    BOOST_CHECK_CLOSE_FRACTION(
266       ::boost::math::cdf(
267       rayleigh_distribution<double>(2.),
268       static_cast<double>(2)), // x
269       static_cast<double>(1- exp_minus_half<double>()), // p
270          1e-15); // %
271 
272    BOOST_CHECK_CLOSE_FRACTION(
273       ::boost::math::cdf(
274       rayleigh_distribution<double>(3.),
275       static_cast<double>(3)), // x
276       static_cast<double>(1- exp_minus_half<double>()), // p
277          1e-15); // %
278 
279    BOOST_CHECK_CLOSE_FRACTION(
280       ::boost::math::cdf(
281       rayleigh_distribution<double>(4.),
282       static_cast<double>(4)), // x
283       static_cast<double>(1- exp_minus_half<double>()), // p
284          1e-15); // %
285 
286    BOOST_CHECK_CLOSE_FRACTION(
287       ::boost::math::cdf(complement(
288       rayleigh_distribution<double>(4.),
289       static_cast<double>(4))), // x
290       static_cast<double>(exp_minus_half<double>()), // q = 1 - p
291          1e-15); // %
292 
293    BOOST_CHECK_CLOSE_FRACTION(
294       ::boost::math::quantile(
295       rayleigh_distribution<double>(4.),
296       static_cast<double>(1- exp_minus_half<double>())), // x
297       static_cast<double>(4), // p
298          1e-15); // %
299 
300    BOOST_CHECK_CLOSE_FRACTION(
301       ::boost::math::quantile(complement(
302       rayleigh_distribution<double>(4.),
303       static_cast<double>(exp_minus_half<double>()))), // x
304       static_cast<double>(4), // p
305          1e-15); // %
306 
307    // (Parameter value, arbitrarily zero, only communicates the floating point type).
308   test_spots(0.0F); // Test float. OK at decdigits = 0 tolerance = 0.0001 %
309   test_spots(0.0); // Test double. OK at decdigits 7, tolerance = 1e07 %
310 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
311   test_spots(0.0L); // Test long double.
312 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
313   test_spots(boost::math::concepts::real_concept(0.)); // Test real concept.
314 #endif
315 #else
316    std::cout << "<note>The long double tests have been disabled on this platform "
317       "either because the long double overloads of the usual math functions are "
318       "not available at all, or because they are too inaccurate for these tests "
319       "to pass.</note>" << std::endl;
320 #endif
321 
322 
323 } // BOOST_AUTO_TEST_CASE( test_main )
324 
325 /*
326 
327 Output is:
328 
329 Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\test_rayleigh.exe"
330 Running 1 test case...
331 Tolerance for type float is 0.000119209 %
332 Tolerance for type double is 2.22045e-013 %
333 Tolerance for type long double is 2.22045e-013 %
334 Tolerance for type class boost::math::concepts::real_concept is 2.22045e-013 %
335 *** No errors detected
336 
337 */
338 
339 
340