]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright John Maddock 2013. |
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 | #ifdef _MSC_VER | |
9 | # define _SCL_SECURE_NO_WARNINGS | |
10 | #endif | |
11 | ||
12 | #include <boost/multiprecision/cpp_bin_float.hpp> | |
13 | #ifdef TEST_MPFR | |
14 | #include <boost/multiprecision/mpfr.hpp> | |
15 | #endif | |
16 | #include <boost/random/mersenne_twister.hpp> | |
17 | #include <boost/random/uniform_int.hpp> | |
18 | #include "libs/multiprecision/test/test.hpp" | |
19 | #include <iostream> | |
20 | #include <iomanip> | |
21 | ||
22 | template <class T> | |
23 | T generate_random() | |
24 | { | |
25 | typedef int e_type; | |
26 | static boost::random::mt19937 gen; | |
27 | T val = gen(); | |
28 | T prev_val = -1; | |
29 | while(val != prev_val) | |
30 | { | |
31 | val *= (gen.max)(); | |
32 | prev_val = val; | |
33 | val += gen(); | |
34 | } | |
35 | e_type e; | |
36 | val = frexp(val, &e); | |
37 | ||
38 | static boost::random::uniform_int_distribution<e_type> ui(-20, 20); | |
39 | return ldexp(val, ui(gen)); | |
40 | } | |
41 | ||
42 | ||
43 | using namespace boost::multiprecision; | |
44 | #ifdef TEST_MPFR | |
45 | typedef number<mpfr_float_backend<35> > good_type; | |
46 | #else | |
47 | typedef double good_type; | |
48 | #endif | |
49 | typedef number<cpp_bin_float<std::numeric_limits<good_type>::digits, digit_base_2>, et_off> test_type; | |
50 | ||
51 | void test_special_cases() | |
52 | { | |
53 | test_type max_val = (std::numeric_limits<test_type>::max)(); | |
54 | test_type min_val = (std::numeric_limits<test_type>::min)(); | |
55 | test_type eps = std::numeric_limits<test_type>::epsilon(); | |
56 | test_type inf_val = (std::numeric_limits<test_type>::infinity)(); | |
57 | test_type nan_val = (std::numeric_limits<test_type>::quiet_NaN)(); | |
58 | test_type half = 0.5; | |
59 | test_type one_point_5 = 1.5; | |
60 | ||
61 | BOOST_CHECK((boost::math::isnormal)(max_val)); | |
62 | BOOST_CHECK((boost::math::isnormal)(-max_val)); | |
63 | BOOST_CHECK((boost::math::isnormal)(min_val)); | |
64 | BOOST_CHECK((boost::math::isnormal)(-min_val)); | |
65 | BOOST_CHECK((boost::math::isinf)(inf_val)); | |
66 | BOOST_CHECK((boost::math::isinf)(-inf_val)); | |
67 | BOOST_CHECK((boost::math::isnan)(nan_val)); | |
68 | BOOST_CHECK((boost::math::isnan)(-nan_val)); | |
69 | ||
70 | if(std::numeric_limits<test_type>::has_denorm) | |
71 | min_val = std::numeric_limits<test_type>::denorm_min(); | |
72 | ||
73 | // Adding epsilon will increment 1.0: | |
74 | BOOST_CHECK(test_type(1) + eps != test_type(1)); | |
75 | BOOST_CHECK(test_type(1) + eps / 2 == test_type(1)); | |
76 | // But it's not the smallest value that will do that: | |
77 | test_type small = 1 + eps; | |
78 | small = ldexp(small, -std::numeric_limits<test_type>::digits); | |
79 | BOOST_CHECK(test_type(1) + small != test_type(1)); | |
80 | // And if we increment 1.0 first, then an even smaller | |
81 | // addition will round up: | |
82 | test_type one_next = test_type(1) + eps; | |
83 | BOOST_CHECK(one_next + eps / 2 != one_next); | |
84 | ||
85 | // Overflow: | |
86 | BOOST_CHECK_EQUAL(max_val + max_val * eps, inf_val); | |
87 | BOOST_CHECK_EQUAL(-max_val - max_val * eps, -inf_val); | |
88 | BOOST_CHECK_EQUAL(max_val * 2, inf_val); | |
89 | BOOST_CHECK_EQUAL(max_val * -2, -inf_val); | |
90 | BOOST_CHECK_EQUAL(max_val / half, inf_val); | |
91 | BOOST_CHECK_EQUAL(max_val / -half, -inf_val); | |
92 | BOOST_CHECK_EQUAL(max_val / min_val, inf_val); | |
93 | BOOST_CHECK_EQUAL(max_val / -min_val, -inf_val); | |
94 | // Underflow: | |
95 | BOOST_CHECK_EQUAL(min_val * 2 - one_point_5 * min_val, 0); | |
96 | BOOST_CHECK_EQUAL(-min_val * 2 + one_point_5 * min_val, 0); | |
97 | BOOST_CHECK_EQUAL(min_val / 2, 0); | |
98 | BOOST_CHECK_EQUAL(min_val / max_val, 0); | |
99 | BOOST_CHECK_EQUAL(min_val * half, 0); | |
100 | BOOST_CHECK_EQUAL(min_val - min_val, 0); | |
101 | BOOST_CHECK_EQUAL(max_val - max_val, 0); | |
102 | BOOST_CHECK_EQUAL(-min_val + min_val, 0); | |
103 | BOOST_CHECK_EQUAL(-max_val + max_val, 0); | |
104 | // Things which should not over/underflow: | |
105 | BOOST_CHECK_EQUAL((min_val * 2) / 2, min_val); | |
106 | BOOST_CHECK_EQUAL((max_val / 2) * 2, max_val); | |
107 | BOOST_CHECK_GE((min_val * 2.0000001) / 1.9999999999999999, min_val); | |
108 | BOOST_CHECK_LE((max_val / 2.0000001) * 1.9999999999999999, max_val); | |
109 | BOOST_CHECK_EQUAL(min_val * 2 - min_val, min_val); | |
110 | BOOST_CHECK_EQUAL(max_val / 2 + max_val / 2, max_val); | |
111 | // Things involving zero: | |
112 | BOOST_CHECK_EQUAL(max_val + 0, max_val); | |
113 | BOOST_CHECK_EQUAL(max_val - 0, max_val); | |
114 | BOOST_CHECK_EQUAL(0 + max_val, max_val); | |
115 | BOOST_CHECK_EQUAL(0 - max_val, -max_val); | |
116 | BOOST_CHECK_EQUAL(max_val * 0, 0); | |
117 | BOOST_CHECK_EQUAL(0 * max_val, 0); | |
118 | BOOST_CHECK_EQUAL(max_val / 0, inf_val); | |
119 | BOOST_CHECK_EQUAL(0 / max_val, 0); | |
120 | BOOST_CHECK_EQUAL(-max_val / 0, -inf_val); | |
121 | BOOST_CHECK_EQUAL(0 / -max_val, 0); | |
122 | // Things involving infinity: | |
123 | BOOST_CHECK_EQUAL(inf_val + 2, inf_val); | |
124 | BOOST_CHECK_EQUAL(inf_val - 2, inf_val); | |
125 | BOOST_CHECK_EQUAL(inf_val + -2, inf_val); | |
126 | BOOST_CHECK_EQUAL(inf_val - -2, inf_val); | |
127 | BOOST_CHECK_EQUAL(-inf_val + 2, -inf_val); | |
128 | BOOST_CHECK_EQUAL(-inf_val - 2, -inf_val); | |
129 | BOOST_CHECK_EQUAL(-inf_val + -2, -inf_val); | |
130 | BOOST_CHECK_EQUAL(-inf_val - -2, -inf_val); | |
131 | ||
132 | BOOST_CHECK_EQUAL(2 + inf_val, inf_val); | |
133 | BOOST_CHECK_EQUAL(2 - inf_val, -inf_val); | |
134 | BOOST_CHECK_EQUAL(-2 + inf_val, inf_val); | |
135 | BOOST_CHECK_EQUAL(-2 - inf_val, -inf_val); | |
136 | BOOST_CHECK_EQUAL(2 + (-inf_val), -inf_val); | |
137 | BOOST_CHECK_EQUAL(2 - (-inf_val), inf_val); | |
138 | BOOST_CHECK_EQUAL(-2 + (-inf_val), -inf_val); | |
139 | BOOST_CHECK_EQUAL(-2 - (-inf_val), inf_val); | |
140 | ||
141 | BOOST_CHECK_EQUAL(sqrt(inf_val), inf_val); | |
142 | BOOST_CHECK(boost::math::isnan(sqrt(-inf_val))); | |
143 | ||
144 | BOOST_CHECK_EQUAL(inf_val + test_type(2), inf_val); | |
145 | BOOST_CHECK_EQUAL(inf_val - test_type(2), inf_val); | |
146 | BOOST_CHECK_EQUAL(inf_val + test_type(-2), inf_val); | |
147 | BOOST_CHECK_EQUAL(inf_val - test_type(-2), inf_val); | |
148 | BOOST_CHECK_EQUAL(-inf_val + test_type(2), -inf_val); | |
149 | BOOST_CHECK_EQUAL(-inf_val - test_type(2), -inf_val); | |
150 | BOOST_CHECK_EQUAL(-inf_val + test_type(-2), -inf_val); | |
151 | BOOST_CHECK_EQUAL(-inf_val - test_type(-2), -inf_val); | |
152 | ||
153 | BOOST_CHECK_EQUAL(test_type(2) + inf_val, inf_val); | |
154 | BOOST_CHECK_EQUAL(test_type(2) - inf_val, -inf_val); | |
155 | BOOST_CHECK_EQUAL(test_type(-2) + inf_val, inf_val); | |
156 | BOOST_CHECK_EQUAL(test_type(-2) - inf_val, -inf_val); | |
157 | BOOST_CHECK_EQUAL(test_type(2) + (-inf_val), -inf_val); | |
158 | BOOST_CHECK_EQUAL(test_type(2) - (-inf_val), inf_val); | |
159 | BOOST_CHECK_EQUAL(test_type(-2) + (-inf_val), -inf_val); | |
160 | BOOST_CHECK_EQUAL(test_type(-2) - (-inf_val), inf_val); | |
161 | ||
162 | BOOST_CHECK((boost::math::isnan)(inf_val - inf_val)); | |
163 | BOOST_CHECK_EQUAL(inf_val * 2, inf_val); | |
164 | BOOST_CHECK_EQUAL(-inf_val * 2, -inf_val); | |
165 | BOOST_CHECK_EQUAL(inf_val * -2, -inf_val); | |
166 | BOOST_CHECK_EQUAL(-inf_val * -2, inf_val); | |
167 | BOOST_CHECK_EQUAL(inf_val * test_type(-2), -inf_val); | |
168 | BOOST_CHECK_EQUAL(-inf_val * test_type(-2), inf_val); | |
169 | BOOST_CHECK((boost::math::isnan)(inf_val * 0)); | |
170 | BOOST_CHECK((boost::math::isnan)(-inf_val * 0)); | |
171 | BOOST_CHECK_EQUAL(inf_val / 2, inf_val); | |
172 | BOOST_CHECK_EQUAL(-inf_val / 2, -inf_val); | |
173 | BOOST_CHECK_EQUAL(inf_val / -2, -inf_val); | |
174 | BOOST_CHECK_EQUAL(-inf_val / -2, inf_val); | |
175 | BOOST_CHECK_EQUAL(inf_val / test_type(-2), -inf_val); | |
176 | BOOST_CHECK_EQUAL(-inf_val / test_type(-2), inf_val); | |
177 | BOOST_CHECK_EQUAL(inf_val / 0, inf_val); | |
178 | BOOST_CHECK_EQUAL(-inf_val / 0, -inf_val); | |
179 | BOOST_CHECK((boost::math::isnan)(inf_val / inf_val)); | |
180 | BOOST_CHECK((boost::math::isnan)(-inf_val / inf_val)); | |
181 | // Things involving nan: | |
182 | BOOST_CHECK((boost::math::isnan)(nan_val + 2)); | |
183 | BOOST_CHECK((boost::math::isnan)(nan_val - 2)); | |
184 | BOOST_CHECK((boost::math::isnan)(nan_val + 0)); | |
185 | BOOST_CHECK((boost::math::isnan)(nan_val - 0)); | |
186 | BOOST_CHECK((boost::math::isnan)(nan_val + inf_val)); | |
187 | BOOST_CHECK((boost::math::isnan)(nan_val - inf_val)); | |
188 | BOOST_CHECK((boost::math::isnan)(nan_val + nan_val)); | |
189 | BOOST_CHECK((boost::math::isnan)(nan_val - nan_val)); | |
190 | BOOST_CHECK((boost::math::isnan)(2 + nan_val)); | |
191 | BOOST_CHECK((boost::math::isnan)(2 - nan_val)); | |
192 | BOOST_CHECK((boost::math::isnan)(0 - nan_val)); | |
193 | BOOST_CHECK((boost::math::isnan)(0 - nan_val)); | |
194 | BOOST_CHECK((boost::math::isnan)(inf_val + nan_val)); | |
195 | BOOST_CHECK((boost::math::isnan)(inf_val - nan_val)); | |
196 | BOOST_CHECK((boost::math::isnan)(nan_val * 2)); | |
197 | BOOST_CHECK((boost::math::isnan)(nan_val / 2)); | |
198 | BOOST_CHECK((boost::math::isnan)(nan_val * 0)); | |
199 | BOOST_CHECK((boost::math::isnan)(nan_val / 0)); | |
200 | BOOST_CHECK((boost::math::isnan)(nan_val * inf_val)); | |
201 | BOOST_CHECK((boost::math::isnan)(nan_val / inf_val)); | |
202 | BOOST_CHECK((boost::math::isnan)(nan_val * nan_val)); | |
203 | BOOST_CHECK((boost::math::isnan)(nan_val / nan_val)); | |
204 | BOOST_CHECK((boost::math::isnan)(2 * nan_val)); | |
205 | BOOST_CHECK((boost::math::isnan)(2 / nan_val)); | |
206 | BOOST_CHECK((boost::math::isnan)(0 / nan_val)); | |
207 | BOOST_CHECK((boost::math::isnan)(0 / nan_val)); | |
208 | BOOST_CHECK((boost::math::isnan)(inf_val * nan_val)); | |
209 | BOOST_CHECK((boost::math::isnan)(inf_val / nan_val)); | |
210 | // Corner cases: | |
211 | BOOST_CHECK_EQUAL((max_val * half) / half, max_val); | |
212 | BOOST_CHECK_EQUAL((max_val / 2) * 2, max_val); | |
213 | BOOST_CHECK_EQUAL((min_val / half) * half, min_val); | |
214 | BOOST_CHECK_EQUAL((min_val * 2) / 2, min_val); | |
215 | BOOST_CHECK_EQUAL(max_val + min_val, max_val); | |
216 | BOOST_CHECK_EQUAL(min_val + max_val, max_val); | |
217 | BOOST_CHECK_EQUAL(max_val - min_val, max_val); | |
218 | BOOST_CHECK_EQUAL(min_val - max_val, -max_val); | |
219 | // Signed zeros: | |
220 | BOOST_CHECK(boost::math::signbit(min_val * -min_val)); | |
221 | BOOST_CHECK(boost::math::signbit(min_val * min_val) == 0); | |
222 | BOOST_CHECK(boost::math::signbit(-min_val * -min_val) == 0); | |
223 | BOOST_CHECK(boost::math::signbit(-min_val * min_val)); | |
224 | BOOST_CHECK(boost::math::signbit(min_val / max_val) == 0); | |
225 | BOOST_CHECK(boost::math::signbit(min_val / -max_val)); | |
226 | BOOST_CHECK(boost::math::signbit(-min_val / -max_val) == 0); | |
227 | BOOST_CHECK(boost::math::signbit(-min_val / max_val)); | |
228 | BOOST_CHECK(boost::math::signbit(min_val / 2) == 0); | |
229 | BOOST_CHECK(boost::math::signbit(min_val / -2)); | |
230 | BOOST_CHECK(boost::math::signbit(-min_val / -2) == 0); | |
231 | BOOST_CHECK(boost::math::signbit(-min_val / 2)); | |
232 | test_type neg_zero = min_val * -min_val; | |
233 | test_type zero = 0; | |
234 | // Arithmetic involving signed zero: | |
235 | BOOST_CHECK_EQUAL(-neg_zero, 0); | |
236 | BOOST_CHECK(!boost::math::signbit(-neg_zero)); | |
237 | BOOST_CHECK_EQUAL(neg_zero + 2, 2); | |
238 | BOOST_CHECK_EQUAL(neg_zero + test_type(2), 2); | |
239 | BOOST_CHECK_EQUAL(2 + neg_zero, 2); | |
240 | BOOST_CHECK_EQUAL(test_type(2) + neg_zero, 2); | |
241 | BOOST_CHECK_EQUAL(neg_zero + -2, -2); | |
242 | BOOST_CHECK_EQUAL(neg_zero + test_type(-2), -2); | |
243 | BOOST_CHECK_EQUAL(-2 + neg_zero, -2); | |
244 | BOOST_CHECK_EQUAL(test_type(-2) + neg_zero, -2); | |
245 | BOOST_CHECK_EQUAL(neg_zero - 2, -2); | |
246 | BOOST_CHECK_EQUAL(neg_zero - test_type(2), -2); | |
247 | BOOST_CHECK_EQUAL(2 - neg_zero, 2); | |
248 | BOOST_CHECK_EQUAL(test_type(2) - neg_zero, 2); | |
249 | BOOST_CHECK_EQUAL(neg_zero - -2, 2); | |
250 | BOOST_CHECK_EQUAL(neg_zero - test_type(-2), 2); | |
251 | BOOST_CHECK_EQUAL(-2 - neg_zero, -2); | |
252 | BOOST_CHECK_EQUAL(test_type(-2) - neg_zero, -2); | |
253 | BOOST_CHECK(!boost::math::signbit(test_type(2) + test_type(-2))); | |
254 | BOOST_CHECK(!boost::math::signbit(test_type(2) - test_type(2))); | |
255 | BOOST_CHECK(!boost::math::signbit(test_type(-2) - test_type(-2))); | |
256 | BOOST_CHECK(!boost::math::signbit(test_type(-2) + test_type(2))); | |
257 | BOOST_CHECK(!boost::math::signbit(zero + zero)); | |
258 | BOOST_CHECK(!boost::math::signbit(zero - zero)); | |
259 | BOOST_CHECK(!boost::math::signbit(neg_zero + zero)); | |
260 | BOOST_CHECK(!boost::math::signbit(zero + neg_zero)); | |
261 | BOOST_CHECK(boost::math::signbit(neg_zero + neg_zero)); | |
262 | BOOST_CHECK(boost::math::signbit(neg_zero - zero)); | |
263 | BOOST_CHECK(!boost::math::signbit(zero - neg_zero)); | |
264 | BOOST_CHECK(!boost::math::signbit(neg_zero - neg_zero)); | |
265 | small = 0.25; | |
266 | BOOST_CHECK(!boost::math::signbit(floor(small))); | |
267 | BOOST_CHECK(!boost::math::signbit(round(small))); | |
268 | BOOST_CHECK(!boost::math::signbit(trunc(small))); | |
269 | small = -small; | |
270 | BOOST_CHECK(boost::math::signbit(ceil(small))); | |
271 | BOOST_CHECK(boost::math::signbit(round(small))); | |
272 | BOOST_CHECK(boost::math::signbit(trunc(small))); | |
273 | ||
274 | ||
275 | BOOST_CHECK_EQUAL(neg_zero * 2, 0); | |
276 | BOOST_CHECK_EQUAL(neg_zero * test_type(2), 0); | |
277 | BOOST_CHECK_EQUAL(2 * neg_zero, 0); | |
278 | BOOST_CHECK_EQUAL(test_type(2) * neg_zero, 0); | |
279 | BOOST_CHECK_EQUAL(neg_zero * -2, 0); | |
280 | BOOST_CHECK_EQUAL(neg_zero * test_type(-2), 0); | |
281 | BOOST_CHECK_EQUAL(-2 * neg_zero, 0); | |
282 | BOOST_CHECK_EQUAL(test_type(-2) * neg_zero, 0); | |
283 | BOOST_CHECK(boost::math::signbit(neg_zero * 2)); | |
284 | BOOST_CHECK(boost::math::signbit(neg_zero * test_type(2))); | |
285 | BOOST_CHECK(boost::math::signbit(2 * neg_zero)); | |
286 | BOOST_CHECK(boost::math::signbit(test_type(2) * neg_zero)); | |
287 | BOOST_CHECK(!boost::math::signbit(neg_zero * -2)); | |
288 | BOOST_CHECK(!boost::math::signbit(neg_zero * test_type(-2))); | |
289 | BOOST_CHECK(!boost::math::signbit(-2 * neg_zero)); | |
290 | BOOST_CHECK(!boost::math::signbit(test_type(-2) * neg_zero)); | |
291 | ||
292 | BOOST_CHECK_EQUAL(neg_zero / 2, 0); | |
293 | BOOST_CHECK_EQUAL(neg_zero / test_type(2), 0); | |
294 | BOOST_CHECK_EQUAL(2 / neg_zero, -inf_val); | |
295 | BOOST_CHECK_EQUAL(test_type(2) / neg_zero, -inf_val); | |
296 | BOOST_CHECK_EQUAL(neg_zero / -2, 0); | |
297 | BOOST_CHECK_EQUAL(neg_zero / test_type(-2), 0); | |
298 | BOOST_CHECK_EQUAL(-2 / neg_zero, inf_val); | |
299 | BOOST_CHECK_EQUAL(test_type(-2) / neg_zero, inf_val); | |
300 | BOOST_CHECK(boost::math::signbit(neg_zero / 2)); | |
301 | BOOST_CHECK(boost::math::signbit(neg_zero / test_type(2))); | |
302 | BOOST_CHECK(boost::math::signbit(2 / neg_zero)); | |
303 | BOOST_CHECK(boost::math::signbit(test_type(2) / neg_zero)); | |
304 | BOOST_CHECK(!boost::math::signbit(neg_zero / -2)); | |
305 | BOOST_CHECK(!boost::math::signbit(neg_zero / test_type(-2))); | |
306 | BOOST_CHECK(!boost::math::signbit(-2 / neg_zero)); | |
307 | BOOST_CHECK(!boost::math::signbit(test_type(-2) / neg_zero)); | |
308 | ||
309 | BOOST_CHECK(boost::math::signbit(neg_zero.convert_to<double>())); | |
310 | BOOST_CHECK(boost::math::signbit(neg_zero.convert_to<float>())); | |
311 | BOOST_CHECK(boost::math::signbit(neg_zero.convert_to<long double>())); | |
312 | BOOST_CHECK(!boost::math::signbit(zero.convert_to<double>())); | |
313 | BOOST_CHECK(!boost::math::signbit(zero.convert_to<float>())); | |
314 | BOOST_CHECK(!boost::math::signbit(zero.convert_to<long double>())); | |
315 | ||
316 | // Conversions to other types of special values: | |
317 | if(std::numeric_limits<float>::has_infinity) | |
318 | { | |
319 | BOOST_CHECK_EQUAL(inf_val.convert_to<float>(), std::numeric_limits<float>::infinity()); | |
320 | BOOST_CHECK_EQUAL((-inf_val).convert_to<float>(), -std::numeric_limits<float>::infinity()); | |
321 | } | |
322 | if(std::numeric_limits<float>::has_quiet_NaN) | |
323 | { | |
324 | BOOST_CHECK((boost::math::isnan)(nan_val.convert_to<float>())); | |
325 | } | |
326 | if(std::numeric_limits<double>::has_infinity) | |
327 | { | |
328 | BOOST_CHECK_EQUAL(inf_val.convert_to<double>(), std::numeric_limits<double>::infinity()); | |
329 | BOOST_CHECK_EQUAL((-inf_val).convert_to<double>(), -std::numeric_limits<double>::infinity()); | |
330 | } | |
331 | if(std::numeric_limits<double>::has_quiet_NaN) | |
332 | { | |
333 | BOOST_CHECK((boost::math::isnan)(nan_val.convert_to<double>())); | |
334 | } | |
335 | if(std::numeric_limits<long double>::has_infinity) | |
336 | { | |
337 | BOOST_CHECK_EQUAL(inf_val.convert_to<long double>(), std::numeric_limits<long double>::infinity()); | |
338 | BOOST_CHECK_EQUAL((-inf_val).convert_to<long double>(), -std::numeric_limits<long double>::infinity()); | |
339 | } | |
340 | if(std::numeric_limits<long double>::has_quiet_NaN) | |
341 | { | |
342 | BOOST_CHECK((boost::math::isnan)(nan_val.convert_to<long double>())); | |
343 | } | |
344 | } | |
345 | ||
346 | int main() | |
347 | { | |
348 | test_special_cases(); | |
349 | unsigned error_count = 0; | |
350 | for(unsigned i = 0; i < 100000; ++i) | |
351 | { | |
352 | good_type a = generate_random<good_type>(); | |
353 | good_type b = generate_random<good_type>(); | |
354 | test_type ta(a); | |
355 | test_type tb(b); | |
356 | ||
357 | BOOST_CHECK_EQUAL(test_type(a * b), ta * tb); | |
358 | BOOST_CHECK_EQUAL(test_type(-a * b), -ta * tb); | |
359 | BOOST_CHECK_EQUAL(test_type(a * -b), ta * -tb); | |
360 | BOOST_CHECK_EQUAL(test_type(-a * -b), -ta * -tb); | |
361 | ||
362 | BOOST_CHECK_EQUAL(test_type(a + b), ta + tb); | |
363 | BOOST_CHECK_EQUAL(test_type(-a + b), -ta + tb); | |
364 | BOOST_CHECK_EQUAL(test_type(a + -b), ta + -tb); | |
365 | BOOST_CHECK_EQUAL(test_type(-a + -b), -ta + -tb); | |
366 | ||
367 | BOOST_CHECK_EQUAL(test_type(a - b), ta - tb); | |
368 | BOOST_CHECK_EQUAL(test_type(-a - b), -ta - tb); | |
369 | BOOST_CHECK_EQUAL(test_type(a - -b), ta - -tb); | |
370 | BOOST_CHECK_EQUAL(test_type(-a - -b), -ta - -tb); | |
371 | ||
372 | BOOST_CHECK_EQUAL(test_type(a / b), ta / tb); | |
373 | BOOST_CHECK_EQUAL(test_type(-a / b), -ta / tb); | |
374 | BOOST_CHECK_EQUAL(test_type(a / -b), ta / -tb); | |
375 | BOOST_CHECK_EQUAL(test_type(-a / -b), -ta / -tb); | |
376 | ||
377 | BOOST_CHECK_EQUAL(test_type(sqrt(a)), sqrt(ta)); | |
378 | BOOST_CHECK_EQUAL(test_type(floor(a)), floor(ta)); | |
379 | BOOST_CHECK_EQUAL(test_type(floor(-a)), floor(-ta)); | |
380 | BOOST_CHECK_EQUAL(test_type(ceil(a)), ceil(ta)); | |
381 | BOOST_CHECK_EQUAL(test_type(ceil(-a)), ceil(-ta)); | |
382 | ||
383 | #ifdef TEST_MPFR | |
384 | // | |
385 | // Conversions: | |
386 | // | |
387 | BOOST_CHECK_EQUAL(a.convert_to<double>(), ta.convert_to<double>()); | |
388 | BOOST_CHECK_EQUAL(a.convert_to<float>(), ta.convert_to<float>()); | |
389 | BOOST_CHECK_EQUAL(b.convert_to<double>(), tb.convert_to<double>()); | |
390 | BOOST_CHECK_EQUAL(b.convert_to<float>(), tb.convert_to<float>()); | |
391 | #else | |
392 | BOOST_CHECK_EQUAL(a, ta.convert_to<double>()); | |
393 | BOOST_CHECK_EQUAL(static_cast<float>(a), ta.convert_to<float>()); | |
394 | BOOST_CHECK_EQUAL(b, tb.convert_to<double>()); | |
395 | BOOST_CHECK_EQUAL(static_cast<float>(b), tb.convert_to<float>()); | |
396 | #endif | |
397 | ||
398 | static boost::random::mt19937 i_gen; | |
399 | ||
400 | int si = i_gen(); | |
401 | BOOST_CHECK_EQUAL(test_type(a * si), ta * si); | |
402 | BOOST_CHECK_EQUAL(test_type(-a * si), -ta * si); | |
403 | BOOST_CHECK_EQUAL(test_type(-a * -si), -ta * -si); | |
404 | BOOST_CHECK_EQUAL(test_type(a * -si), ta * -si); | |
405 | unsigned ui = std::abs(si); | |
406 | BOOST_CHECK_EQUAL(test_type(a * ui), ta * ui); | |
407 | BOOST_CHECK_EQUAL(test_type(-a * ui), -ta * ui); | |
408 | ||
409 | // Divide: | |
410 | BOOST_CHECK_EQUAL(test_type(a / si), ta / si); | |
411 | BOOST_CHECK_EQUAL(test_type(-a / si), -ta / si); | |
412 | BOOST_CHECK_EQUAL(test_type(-a / -si), -ta / -si); | |
413 | BOOST_CHECK_EQUAL(test_type(a / -si), ta / -si); | |
414 | BOOST_CHECK_EQUAL(test_type(a / ui), ta / ui); | |
415 | BOOST_CHECK_EQUAL(test_type(-a / ui), -ta / ui); | |
416 | // Error reporting: | |
417 | if(boost::detail::test_errors() != error_count) | |
418 | { | |
419 | error_count = boost::detail::test_errors(); | |
420 | std::cout << std::setprecision(std::numeric_limits<test_type>::max_digits10) << std::scientific; | |
421 | std::cout << "a (mpfr) = " << a << std::endl; | |
422 | std::cout << "a (test) = " << ta << std::endl; | |
423 | std::cout << "b (mpfr) = " << b << std::endl; | |
424 | std::cout << "b (test) = " << tb << std::endl; | |
425 | std::cout << "si = " << si << std::endl; | |
426 | std::cout << "ui = " << ui << std::endl; | |
427 | } | |
428 | } | |
429 | return boost::report_errors(); | |
430 | } | |
431 |