1 ///////////////////////////////////////////////////////////////
2 // Copyright 2012 John Maddock. Distributed under the Boost
3 // Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
5
6 #ifdef TEST_VLD
7 #include <vld.h>
8 #endif
9
10 #include <boost/math/special_functions/pow.hpp>
11 #include <boost/math/common_factor_rt.hpp>
12 #include "test.hpp"
13
14 template <class T>
15 struct is_boost_rational : public boost::mpl::false_{};
16
17 #ifdef BOOST_MSVC
18 // warning C4127: conditional expression is constant
19 #pragma warning(disable:4127)
20 #endif
21
22 template <class Target, class Source>
23 Target checked_lexical_cast(const Source& val)
24 {
25 try
26 {
27 return boost::lexical_cast<Target>(val);
28 }
29 catch(...)
30 {
31 std::cerr << "Error in lexical cast\nSource type = " << typeid(Source).name() << " \"" << val << "\"\n";
32 std::cerr << "Target type = " << typeid(Target).name() << std::endl;
33 throw;
34 }
35 }
36
37
isfloat(float)38 bool isfloat(float){ return true; }
isfloat(double)39 bool isfloat(double){ return true; }
isfloat(long double)40 bool isfloat(long double){ return true; }
isfloat(T)41 template <class T> bool isfloat(T){ return false; }
42
43 namespace detail{
44
45 template<class tag, class Arg1, class Arg2, class Arg3, class Arg4>
46 typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type
abs(boost::multiprecision::detail::expression<tag,Arg1,Arg2,Arg3,Arg4> const & v)47 abs(boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> const& v)
48 {
49 typedef typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type result_type;
50 return v < 0 ? result_type(-v) : result_type(v);
51 }
52
53 }
54
55 template <class T>
56 struct is_twos_complement_integer : public boost::mpl::true_ {};
57
58 template <class T>
59 struct related_type
60 {
61 typedef T type;
62 };
63
64 template <class Real, class Val>
test_comparisons(Val,Val,const boost::mpl::false_)65 void test_comparisons(Val, Val, const boost::mpl::false_)
66 {}
67
normalize_compare_result(int r)68 int normalize_compare_result(int r)
69 {
70 return r > 0 ? 1 : r < 0 ? -1 : 0;
71 }
72
73 template <class Real, class Val>
test_comparisons(Val a,Val b,const boost::mpl::true_)74 void test_comparisons(Val a, Val b, const boost::mpl::true_)
75 {
76 Real r1(a);
77 Real r2(b);
78 Real z(1);
79
80 int cr = a < b ? -1 : a > b ? 1 : 0;
81
82 BOOST_CHECK_EQUAL(r1 == r2, a == b);
83 BOOST_CHECK_EQUAL(r1 != r2, a != b);
84 BOOST_CHECK_EQUAL(r1 <= r2, a <= b);
85 BOOST_CHECK_EQUAL(r1 < r2, a < b);
86 BOOST_CHECK_EQUAL(r1 >= r2, a >= b);
87 BOOST_CHECK_EQUAL(r1 > r2, a > b);
88
89 BOOST_CHECK_EQUAL(r1 == b, a == b);
90 BOOST_CHECK_EQUAL(r1 != b, a != b);
91 BOOST_CHECK_EQUAL(r1 <= b, a <= b);
92 BOOST_CHECK_EQUAL(r1 < b, a < b);
93 BOOST_CHECK_EQUAL(r1 >= b, a >= b);
94 BOOST_CHECK_EQUAL(r1 > b, a > b);
95
96 BOOST_CHECK_EQUAL(a == r2, a == b);
97 BOOST_CHECK_EQUAL(a != r2, a != b);
98 BOOST_CHECK_EQUAL(a <= r2, a <= b);
99 BOOST_CHECK_EQUAL(a < r2, a < b);
100 BOOST_CHECK_EQUAL(a >= r2, a >= b);
101 BOOST_CHECK_EQUAL(a > r2, a > b);
102
103 BOOST_CHECK_EQUAL(r1*z == r2, a == b);
104 BOOST_CHECK_EQUAL(r1*z != r2, a != b);
105 BOOST_CHECK_EQUAL(r1*z <= r2, a <= b);
106 BOOST_CHECK_EQUAL(r1*z < r2, a < b);
107 BOOST_CHECK_EQUAL(r1*z >= r2, a >= b);
108 BOOST_CHECK_EQUAL(r1*z > r2, a > b);
109
110 BOOST_CHECK_EQUAL(r1 == r2*z, a == b);
111 BOOST_CHECK_EQUAL(r1 != r2*z, a != b);
112 BOOST_CHECK_EQUAL(r1 <= r2*z, a <= b);
113 BOOST_CHECK_EQUAL(r1 < r2*z, a < b);
114 BOOST_CHECK_EQUAL(r1 >= r2*z, a >= b);
115 BOOST_CHECK_EQUAL(r1 > r2*z, a > b);
116
117 BOOST_CHECK_EQUAL(r1*z == r2*z, a == b);
118 BOOST_CHECK_EQUAL(r1*z != r2*z, a != b);
119 BOOST_CHECK_EQUAL(r1*z <= r2*z, a <= b);
120 BOOST_CHECK_EQUAL(r1*z < r2*z, a < b);
121 BOOST_CHECK_EQUAL(r1*z >= r2*z, a >= b);
122 BOOST_CHECK_EQUAL(r1*z > r2*z, a > b);
123
124 BOOST_CHECK_EQUAL(r1*z == b, a == b);
125 BOOST_CHECK_EQUAL(r1*z != b, a != b);
126 BOOST_CHECK_EQUAL(r1*z <= b, a <= b);
127 BOOST_CHECK_EQUAL(r1*z < b, a < b);
128 BOOST_CHECK_EQUAL(r1*z >= b, a >= b);
129 BOOST_CHECK_EQUAL(r1*z > b, a > b);
130
131 BOOST_CHECK_EQUAL(a == r2*z, a == b);
132 BOOST_CHECK_EQUAL(a != r2*z, a != b);
133 BOOST_CHECK_EQUAL(a <= r2*z, a <= b);
134 BOOST_CHECK_EQUAL(a < r2*z, a < b);
135 BOOST_CHECK_EQUAL(a >= r2*z, a >= b);
136 BOOST_CHECK_EQUAL(a > r2*z, a > b);
137
138 BOOST_CHECK_EQUAL(normalize_compare_result(r1.compare(r2)), cr);
139 BOOST_CHECK_EQUAL(normalize_compare_result(r2.compare(r1)), -cr);
140 BOOST_CHECK_EQUAL(normalize_compare_result(r1.compare(b)), cr);
141 BOOST_CHECK_EQUAL(normalize_compare_result(r2.compare(a)), -cr);
142 }
143
144 template <class Real, class Exp>
test_conditional(Real v,Exp e)145 void test_conditional(Real v, Exp e)
146 {
147 //
148 // Verify that Exp is usable in Boolean contexts, and has the same value as v:
149 //
150 if(e)
151 {
152 BOOST_CHECK(v);
153 }
154 else
155 {
156 BOOST_CHECK(!v);
157 }
158 if(!e)
159 {
160 BOOST_CHECK(!v);
161 }
162 else
163 {
164 BOOST_CHECK(v);
165 }
166 }
167
168 template <class Real>
test_complement(Real a,Real b,Real c,const boost::mpl::true_ &)169 void test_complement(Real a, Real b, Real c, const boost::mpl::true_&)
170 {
171 int i = 1020304;
172 int j = 56789123;
173 int sign_mask = ~0;
174 if(std::numeric_limits<Real>::is_signed)
175 {
176 BOOST_CHECK_EQUAL(~a , (~i & sign_mask));
177 c = a & ~b;
178 BOOST_CHECK_EQUAL(c , (i & (~j & sign_mask)));
179 c = ~(a | b);
180 BOOST_CHECK_EQUAL(c , (~(i | j) & sign_mask));
181 }
182 else
183 {
184 BOOST_CHECK_EQUAL((~a & a) , 0);
185 }
186 }
187
188 template <class Real>
test_complement(Real,Real,Real,const boost::mpl::false_ &)189 void test_complement(Real, Real, Real, const boost::mpl::false_&)
190 {
191 }
192
193 template <class Real, class T>
test_integer_ops(const T &)194 void test_integer_ops(const T&){}
195
196 template <class Real>
test_rational(const boost::mpl::true_ &)197 void test_rational(const boost::mpl::true_&)
198 {
199 Real a(2);
200 a /= 3;
201 BOOST_CHECK_EQUAL(numerator(a) , 2);
202 BOOST_CHECK_EQUAL(denominator(a) , 3);
203 Real b(4);
204 b /= 6;
205 BOOST_CHECK_EQUAL(a , b);
206
207 //
208 // Check IO code:
209 //
210 std::stringstream ss;
211 ss << a;
212 ss >> b;
213 BOOST_CHECK_EQUAL(a, b);
214 }
215
216 template <class Real>
test_rational(const boost::mpl::false_ &)217 void test_rational(const boost::mpl::false_&)
218 {
219 Real a(2);
220 a /= 3;
221 BOOST_CHECK_EQUAL(numerator(a) , 2);
222 BOOST_CHECK_EQUAL(denominator(a) , 3);
223 Real b(4);
224 b /= 6;
225 BOOST_CHECK_EQUAL(a , b);
226
227 BOOST_CHECK_THROW(Real(a / 0), std::overflow_error);
228 BOOST_CHECK_THROW(Real("3.14"), std::runtime_error);
229 b = Real("2/3");
230 BOOST_CHECK_EQUAL(a, b);
231 //
232 // Check IO code:
233 //
234 std::stringstream ss;
235 ss << a;
236 ss >> b;
237 BOOST_CHECK_EQUAL(a, b);
238 }
239
240 template <class Real>
test_integer_ops(const boost::mpl::int_<boost::multiprecision::number_kind_rational> &)241 void test_integer_ops(const boost::mpl::int_<boost::multiprecision::number_kind_rational>&)
242 {
243 test_rational<Real>(is_boost_rational<Real>());
244 }
245
246 template <class Real>
test_signed_integer_ops(const boost::mpl::true_ &)247 void test_signed_integer_ops(const boost::mpl::true_&)
248 {
249 Real a(20);
250 Real b(7);
251 Real c(5);
252 BOOST_CHECK_EQUAL(-a % c , 0);
253 BOOST_CHECK_EQUAL(-a % b , -20 % 7);
254 BOOST_CHECK_EQUAL(-a % -b , -20 % -7);
255 BOOST_CHECK_EQUAL(a % -b , 20 % -7);
256 BOOST_CHECK_EQUAL(-a % 7 , -20 % 7);
257 BOOST_CHECK_EQUAL(-a % -7 , -20 % -7);
258 BOOST_CHECK_EQUAL(a % -7 , 20 % -7);
259 BOOST_CHECK_EQUAL(-a % 7u , -20 % 7);
260 BOOST_CHECK_EQUAL(-a % a , 0);
261 BOOST_CHECK_EQUAL(-a % 5 , 0);
262 BOOST_CHECK_EQUAL(-a % -5 , 0);
263 BOOST_CHECK_EQUAL(a % -5 , 0);
264
265 b = -b;
266 BOOST_CHECK_EQUAL(a % b , 20 % -7);
267 a = -a;
268 BOOST_CHECK_EQUAL(a % b , -20 % -7);
269 BOOST_CHECK_EQUAL(a % -7 , -20 % -7);
270 b = 7;
271 BOOST_CHECK_EQUAL(a % b , -20 % 7);
272 BOOST_CHECK_EQUAL(a % 7 , -20 % 7);
273 BOOST_CHECK_EQUAL(a % 7u , -20 % 7);
274
275 a = 20;
276 a %= b;
277 BOOST_CHECK_EQUAL(a , 20 % 7);
278 a = -20;
279 a %= b;
280 BOOST_CHECK_EQUAL(a , -20 % 7);
281 a = 20;
282 a %= -b;
283 BOOST_CHECK_EQUAL(a , 20 % -7);
284 a = -20;
285 a %= -b;
286 BOOST_CHECK_EQUAL(a , -20 % -7);
287 a = 5;
288 a %= b - a;
289 BOOST_CHECK_EQUAL(a , 5 % (7-5));
290 a = -20;
291 a %= 7;
292 BOOST_CHECK_EQUAL(a , -20 % 7);
293 a = 20;
294 a %= -7;
295 BOOST_CHECK_EQUAL(a , 20 % -7);
296 a = -20;
297 a %= -7;
298 BOOST_CHECK_EQUAL(a , -20 % -7);
299 #ifndef BOOST_NO_LONG_LONG
300 a = -20;
301 a %= 7uLL;
302 BOOST_CHECK_EQUAL(a , -20 % 7);
303 a = 20;
304 a %= -7LL;
305 BOOST_CHECK_EQUAL(a , 20 % -7);
306 a = -20;
307 a %= -7LL;
308 BOOST_CHECK_EQUAL(a , -20 % -7);
309 #endif
310 a = 400;
311 b = 45;
312 BOOST_CHECK_EQUAL(gcd(a, -45) , boost::math::gcd(400, 45));
313 BOOST_CHECK_EQUAL(lcm(a, -45) , boost::math::lcm(400, 45));
314 BOOST_CHECK_EQUAL(gcd(-400, b) , boost::math::gcd(400, 45));
315 BOOST_CHECK_EQUAL(lcm(-400, b) , boost::math::lcm(400, 45));
316 a = -20;
317 BOOST_CHECK_EQUAL(abs(a) , 20);
318 BOOST_CHECK_EQUAL(abs(-a) , 20);
319 BOOST_CHECK_EQUAL(abs(+a) , 20);
320 a = 20;
321 BOOST_CHECK_EQUAL(abs(a) , 20);
322 BOOST_CHECK_EQUAL(abs(-a) , 20);
323 BOOST_CHECK_EQUAL(abs(+a) , 20);
324 a = -400;
325 b = 45;
326 BOOST_CHECK_EQUAL(gcd(a, b) , boost::math::gcd(-400, 45));
327 BOOST_CHECK_EQUAL(lcm(a, b) , boost::math::lcm(-400, 45));
328 BOOST_CHECK_EQUAL(gcd(a, 45) , boost::math::gcd(-400, 45));
329 BOOST_CHECK_EQUAL(lcm(a, 45) , boost::math::lcm(-400, 45));
330 BOOST_CHECK_EQUAL(gcd(-400, b) , boost::math::gcd(-400, 45));
331 BOOST_CHECK_EQUAL(lcm(-400, b) , boost::math::lcm(-400, 45));
332 Real r;
333 divide_qr(a, b, c, r);
334 BOOST_CHECK_EQUAL(c , a / b);
335 BOOST_CHECK_EQUAL(r , a % b);
336 BOOST_CHECK_EQUAL(integer_modulus(a, 57) , abs(a % 57));
337 b = -57;
338 divide_qr(a, b, c, r);
339 BOOST_CHECK_EQUAL(c , a / b);
340 BOOST_CHECK_EQUAL(r , a % b);
341 BOOST_CHECK_EQUAL(integer_modulus(a, -57) , abs(a % -57));
342 a = 458;
343 divide_qr(a, b, c, r);
344 BOOST_CHECK_EQUAL(c , a / b);
345 BOOST_CHECK_EQUAL(r , a % b);
346 BOOST_CHECK_EQUAL(integer_modulus(a, -57) , abs(a % -57));
347 }
348 template <class Real>
test_signed_integer_ops(const boost::mpl::false_ &)349 void test_signed_integer_ops(const boost::mpl::false_&)
350 {
351 }
352
353 template <class Real>
test_integer_ops(const boost::mpl::int_<boost::multiprecision::number_kind_integer> &)354 void test_integer_ops(const boost::mpl::int_<boost::multiprecision::number_kind_integer>&)
355 {
356 test_signed_integer_ops<Real>(boost::mpl::bool_<std::numeric_limits<Real>::is_signed>());
357
358 Real a(20);
359 Real b(7);
360 Real c(5);
361 BOOST_CHECK_EQUAL(a % b , 20 % 7);
362 BOOST_CHECK_EQUAL(a % 7 , 20 % 7);
363 BOOST_CHECK_EQUAL(a % 7u , 20 % 7);
364 BOOST_CHECK_EQUAL(a % a , 0);
365 BOOST_CHECK_EQUAL(a % c , 0);
366 BOOST_CHECK_EQUAL(a % 5 , 0);
367 a = a % (b + 0);
368 BOOST_CHECK_EQUAL(a , 20 % 7);
369 a = 20;
370 c = (a + 2) % (a - 1);
371 BOOST_CHECK_EQUAL(c , 22 % 19);
372 c = 5;
373 a = b % (a - 15);
374 BOOST_CHECK_EQUAL(a , 7 % 5);
375 a = 20;
376
377 a = 20;
378 a %= 7;
379 BOOST_CHECK_EQUAL(a , 20 % 7);
380 #ifndef BOOST_NO_LONG_LONG
381 a = 20;
382 a %= 7uLL;
383 BOOST_CHECK_EQUAL(a , 20 % 7);
384 #endif
385 a = 20;
386 BOOST_CHECK_EQUAL(++a , 21);
387 BOOST_CHECK_EQUAL(--a , 20);
388 BOOST_CHECK_EQUAL(a++ , 20);
389 BOOST_CHECK_EQUAL(a , 21);
390 BOOST_CHECK_EQUAL(a-- , 21);
391 BOOST_CHECK_EQUAL(a , 20);
392 a = 2000;
393 a <<= 20;
394 BOOST_CHECK_EQUAL(a , 2000L << 20);
395 a >>= 20;
396 BOOST_CHECK_EQUAL(a , 2000);
397 a <<= 20u;
398 BOOST_CHECK_EQUAL(a , 2000L << 20);
399 a >>= 20u;
400 BOOST_CHECK_EQUAL(a , 2000);
401 BOOST_CHECK_THROW(a <<= -20, std::out_of_range);
402 BOOST_CHECK_THROW(a >>= -20, std::out_of_range);
403 BOOST_CHECK_THROW(Real(a << -20), std::out_of_range);
404 BOOST_CHECK_THROW(Real(a >> -20), std::out_of_range);
405 #ifndef BOOST_NO_LONG_LONG
406 if(sizeof(long long) > sizeof(std::size_t))
407 {
408 // extreme values should trigger an exception:
409 BOOST_CHECK_THROW(a >>= (1uLL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range);
410 BOOST_CHECK_THROW(a <<= (1uLL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range);
411 BOOST_CHECK_THROW(a >>= -(1LL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range);
412 BOOST_CHECK_THROW(a <<= -(1LL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range);
413 BOOST_CHECK_THROW(a >>= (1LL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range);
414 BOOST_CHECK_THROW(a <<= (1LL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range);
415 // Unless they fit within range:
416 a = 2000L;
417 BOOST_CHECK_EQUAL((a <<= 20uLL) , (2000L << 20));
418 a = 2000;
419 BOOST_CHECK_EQUAL((a <<= 20LL) , (2000L << 20));
420
421 BOOST_CHECK_THROW(Real(a >> (1uLL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range);
422 BOOST_CHECK_THROW(Real(a <<= (1uLL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range);
423 BOOST_CHECK_THROW(Real(a >>= -(1LL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range);
424 BOOST_CHECK_THROW(Real(a <<= -(1LL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range);
425 BOOST_CHECK_THROW(Real(a >>= (1LL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range);
426 BOOST_CHECK_THROW(Real(a <<= (1LL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range);
427 // Unless they fit within range:
428 a = 2000L;
429 BOOST_CHECK_EQUAL(Real(a << 20uLL) , (2000L << 20));
430 a = 2000;
431 BOOST_CHECK_EQUAL(Real(a << 20LL) , (2000L << 20));
432 }
433 #endif
434 a = 20;
435 b = a << 20;
436 BOOST_CHECK_EQUAL(b , (20 << 20));
437 b = a >> 2;
438 BOOST_CHECK_EQUAL(b , (20 >> 2));
439 b = (a + 2) << 10;
440 BOOST_CHECK_EQUAL(b , (22 << 10));
441 b = (a + 3) >> 3;
442 BOOST_CHECK_EQUAL(b , (23 >> 3));
443 //
444 // Bit fiddling:
445 //
446 int i = 1020304;
447 int j = 56789123;
448 int k = 4523187;
449 a = i;
450 b = j;
451 c = a;
452 c &= b;
453 BOOST_CHECK_EQUAL(c , (i & j));
454 c = a;
455 c &= j;
456 BOOST_CHECK_EQUAL(c , (i & j));
457 c = a;
458 c &= a + b;
459 BOOST_CHECK_EQUAL(c , (i & (i + j)));
460 BOOST_CHECK_EQUAL((a & b) , (i & j));
461 c = k;
462 a = a & (b + k);
463 BOOST_CHECK_EQUAL(a , (i & (j + k)));
464 a = i;
465 a = (b + k) & a;
466 BOOST_CHECK_EQUAL(a , (i & (j + k)));
467 a = i;
468 c = a & b & k;
469 BOOST_CHECK_EQUAL(c , (i&j&k));
470 c = a;
471 c &= (c+b);
472 BOOST_CHECK_EQUAL(c , (i & (i+j)));
473 c = a & (b | 1);
474 BOOST_CHECK_EQUAL(c , (i & (j | 1)));
475
476 test_complement<Real>(a, b, c, typename is_twos_complement_integer<Real>::type());
477
478 a = i;
479 b = j;
480 c = a;
481 c |= b;
482 BOOST_CHECK_EQUAL(c , (i | j));
483 c = a;
484 c |= j;
485 BOOST_CHECK_EQUAL(c , (i | j));
486 c = a;
487 c |= a + b;
488 BOOST_CHECK_EQUAL(c , (i | (i + j)));
489 BOOST_CHECK_EQUAL((a | b) , (i | j));
490 c = k;
491 a = a | (b + k);
492 BOOST_CHECK_EQUAL(a , (i | (j + k)));
493 a = i;
494 a = (b + k) | a;
495 BOOST_CHECK_EQUAL(a , (i | (j + k)));
496 a = i;
497 c = a | b | k;
498 BOOST_CHECK_EQUAL(c , (i|j|k));
499 c = a;
500 c |= (c + b);
501 BOOST_CHECK_EQUAL(c , (i | (i+j)));
502 c = a | (b | 1);
503 BOOST_CHECK_EQUAL(c , (i | (j | 1)));
504
505 a = i;
506 b = j;
507 c = a;
508 c ^= b;
509 BOOST_CHECK_EQUAL(c , (i ^ j));
510 c = a;
511 c ^= j;
512 BOOST_CHECK_EQUAL(c , (i ^ j));
513 c = a;
514 c ^= a + b;
515 BOOST_CHECK_EQUAL(c , (i ^ (i + j)));
516 BOOST_CHECK_EQUAL((a ^ b) , (i ^ j));
517 c = k;
518 a = a ^ (b + k);
519 BOOST_CHECK_EQUAL(a , (i ^ (j + k)));
520 a = i;
521 a = (b + k) ^ a;
522 BOOST_CHECK_EQUAL(a , (i ^ (j + k)));
523 a = i;
524 c = a ^ b ^ k;
525 BOOST_CHECK_EQUAL(c , (i^j^k));
526 c = a;
527 c ^= (c + b);
528 BOOST_CHECK_EQUAL(c , (i ^ (i+j)));
529 c = a ^ (b | 1);
530 BOOST_CHECK_EQUAL(c , (i ^ (j | 1)));
531
532 a = i;
533 b = j;
534 c = k;
535 //
536 // Non-member functions:
537 //
538 a = 400;
539 b = 45;
540 BOOST_CHECK_EQUAL(gcd(a, b) , boost::math::gcd(400, 45));
541 BOOST_CHECK_EQUAL(lcm(a, b) , boost::math::lcm(400, 45));
542 BOOST_CHECK_EQUAL(gcd(a, 45) , boost::math::gcd(400, 45));
543 BOOST_CHECK_EQUAL(lcm(a, 45) , boost::math::lcm(400, 45));
544 BOOST_CHECK_EQUAL(gcd(a, 45u) , boost::math::gcd(400, 45));
545 BOOST_CHECK_EQUAL(lcm(a, 45u) , boost::math::lcm(400, 45));
546 BOOST_CHECK_EQUAL(gcd(400, b) , boost::math::gcd(400, 45));
547 BOOST_CHECK_EQUAL(lcm(400, b) , boost::math::lcm(400, 45));
548 BOOST_CHECK_EQUAL(gcd(400u, b) , boost::math::gcd(400, 45));
549 BOOST_CHECK_EQUAL(lcm(400u, b) , boost::math::lcm(400, 45));
550
551 //
552 // Conditionals involving 2 arg functions:
553 //
554 test_conditional(Real(gcd(a, b)), gcd(a, b));
555
556 Real r;
557 divide_qr(a, b, c, r);
558 BOOST_CHECK_EQUAL(c , a / b);
559 BOOST_CHECK_EQUAL(r , a % b);
560 divide_qr(a + 0, b, c, r);
561 BOOST_CHECK_EQUAL(c , a / b);
562 BOOST_CHECK_EQUAL(r , a % b);
563 divide_qr(a, b+0, c, r);
564 BOOST_CHECK_EQUAL(c , a / b);
565 BOOST_CHECK_EQUAL(r , a % b);
566 divide_qr(a+0, b+0, c, r);
567 BOOST_CHECK_EQUAL(c , a / b);
568 BOOST_CHECK_EQUAL(r , a % b);
569 BOOST_CHECK_EQUAL(integer_modulus(a, 57) , a % 57);
570 for(unsigned i = 0; i < 20; ++i)
571 {
572 if(std::numeric_limits<Real>::is_specialized && (!std::numeric_limits<Real>::is_bounded || ((int)i * 17 < std::numeric_limits<Real>::digits)))
573 {
574 BOOST_CHECK_EQUAL(lsb(Real(1) << (i * 17)) , i * 17);
575 BOOST_CHECK_EQUAL(msb(Real(1) << (i * 17)) , i * 17);
576 BOOST_CHECK(bit_test(Real(1) << (i * 17), i * 17));
577 BOOST_CHECK(!bit_test(Real(1) << (i * 17), i * 17 + 1));
578 if(i)
579 {
580 BOOST_CHECK(!bit_test(Real(1) << (i * 17), i * 17 - 1));
581 }
582 Real zero(0);
583 BOOST_CHECK(bit_test(bit_set(zero, i * 17), i * 17));
584 zero = 0;
585 BOOST_CHECK_EQUAL(bit_flip(zero, i*17) , Real(1) << i * 17);
586 zero = Real(1) << i * 17;
587 BOOST_CHECK_EQUAL(bit_flip(zero, i * 17) , 0);
588 zero = Real(1) << i * 17;
589 BOOST_CHECK_EQUAL(bit_unset(zero, i * 17) , 0);
590 }
591 }
592 //
593 // pow, powm:
594 //
595 BOOST_CHECK_EQUAL(pow(Real(3), 4) , 81);
596 BOOST_CHECK_EQUAL(pow(Real(3) + Real(0), 4) , 81);
597 BOOST_CHECK_EQUAL(powm(Real(3), Real(4), Real(13)) , 81 % 13);
598 BOOST_CHECK_EQUAL(powm(Real(3), Real(4), 13) , 81 % 13);
599 BOOST_CHECK_EQUAL(powm(Real(3), Real(4), Real(13) + 0) , 81 % 13);
600 BOOST_CHECK_EQUAL(powm(Real(3), Real(4) + 0, Real(13)) , 81 % 13);
601 BOOST_CHECK_EQUAL(powm(Real(3), Real(4) + 0, 13) , 81 % 13);
602 BOOST_CHECK_EQUAL(powm(Real(3), Real(4) + 0, Real(13) + 0) , 81 % 13);
603 BOOST_CHECK_EQUAL(powm(Real(3), 4 + 0, Real(13)) , 81 % 13);
604 BOOST_CHECK_EQUAL(powm(Real(3), 4 + 0, 13) , 81 % 13);
605 BOOST_CHECK_EQUAL(powm(Real(3), 4 + 0, Real(13) + 0) , 81 % 13);
606 BOOST_CHECK_EQUAL(powm(Real(3) + 0, Real(4), Real(13)) , 81 % 13);
607 BOOST_CHECK_EQUAL(powm(Real(3) + 0, Real(4), 13) , 81 % 13);
608 BOOST_CHECK_EQUAL(powm(Real(3) + 0, Real(4), Real(13) + 0) , 81 % 13);
609 BOOST_CHECK_EQUAL(powm(Real(3) + 0, Real(4) + 0, Real(13)) , 81 % 13);
610 BOOST_CHECK_EQUAL(powm(Real(3) + 0, Real(4) + 0, 13) , 81 % 13);
611 BOOST_CHECK_EQUAL(powm(Real(3) + 0, Real(4) + 0, Real(13) + 0) , 81 % 13);
612 BOOST_CHECK_EQUAL(powm(Real(3) + 0, 4 + 0, Real(13)) , 81 % 13);
613 BOOST_CHECK_EQUAL(powm(Real(3) + 0, 4 + 0, 13) , 81 % 13);
614 BOOST_CHECK_EQUAL(powm(Real(3) + 0, 4 + 0, Real(13) + 0) , 81 % 13);
615 //
616 // Conditionals involving 3 arg functions:
617 //
618 test_conditional(Real(powm(Real(3), Real(4), Real(13))), powm(Real(3), Real(4), Real(13)));
619
620 //
621 // Things that are expected errors:
622 //
623 BOOST_CHECK_THROW(Real("3.14"), std::runtime_error);
624 BOOST_CHECK_THROW(Real("3L"), std::runtime_error);
625 BOOST_CHECK_THROW(Real(Real(20) / 0u), std::overflow_error);
626 //
627 // Extra tests added for full coverage:
628 //
629 a = 20;
630 b = 7;
631 c = 20 % b;
632 BOOST_CHECK_EQUAL(c , (20 % 7));
633 c = 20 % (b + 0);
634 BOOST_CHECK_EQUAL(c , (20 % 7));
635 c = a & 10;
636 BOOST_CHECK_EQUAL(c , (20 & 10));
637 c = 10 & a;
638 BOOST_CHECK_EQUAL(c , (20 & 10));
639 c = (a + 0) & (b + 0);
640 BOOST_CHECK_EQUAL(c , (20 & 7));
641 c = 10 & (a + 0);
642 BOOST_CHECK_EQUAL(c , (20 & 10));
643 c = 10 | a;
644 BOOST_CHECK_EQUAL(c , (20 | 10));
645 c = (a + 0) | (b + 0);
646 BOOST_CHECK(c == (20 | 7))
647 c = 20 | (b + 0);
648 BOOST_CHECK_EQUAL(c , (20 | 7));
649 c = a ^ 7;
650 BOOST_CHECK_EQUAL(c , (20 ^ 7));
651 c = 20 ^ b;
652 BOOST_CHECK_EQUAL(c , (20 ^ 7));
653 c = (a + 0) ^ (b + 0);
654 BOOST_CHECK_EQUAL(c , (20 ^ 7));
655 c = 20 ^ (b + 0);
656 BOOST_CHECK_EQUAL(c , (20 ^ 7));
657 }
658
659 template <class Real, class T>
test_float_funcs(const T &)660 void test_float_funcs(const T&){}
661
662 template <class Real>
test_float_funcs(const boost::mpl::true_ &)663 void test_float_funcs(const boost::mpl::true_&)
664 {
665 if(boost::multiprecision::is_interval_number<Real>::value)
666 return;
667 //
668 // Test variable reuse in function calls, see https://svn.boost.org/trac/boost/ticket/8326
669 //
670 Real a(2), b(10);
671 a = pow(a, b);
672 BOOST_CHECK_EQUAL(a, 1024);
673 a = 2;
674 b = pow(a, b);
675 BOOST_CHECK_EQUAL(b, 1024);
676 b = 10;
677 a = pow(a, 10);
678 BOOST_CHECK_EQUAL(a, 1024);
679 a = -2;
680 a = abs(a);
681 BOOST_CHECK_EQUAL(a, 2);
682 a = -2;
683 a = fabs(a);
684 BOOST_CHECK_EQUAL(a, 2);
685 a = 2.5;
686 a = floor(a);
687 BOOST_CHECK_EQUAL(a, 2);
688 a = 2.5;
689 a = ceil(a);
690 BOOST_CHECK_EQUAL(a, 3);
691 a = 2.5;
692 a = trunc(a);
693 BOOST_CHECK_EQUAL(a, 2);
694 a = 2.25;
695 a = round(a);
696 BOOST_CHECK_EQUAL(a, 2);
697 a = 2;
698 a = ldexp(a, 1);
699 BOOST_CHECK_EQUAL(a, 4);
700 int i;
701 a = frexp(a, &i);
702 BOOST_CHECK_EQUAL(a, 0.5);
703
704 Real tol = std::numeric_limits<Real>::epsilon() * 3;
705 a = 4;
706 a = sqrt(a);
707 BOOST_CHECK_CLOSE_FRACTION(a, 2, tol);
708 a = 3;
709 a = exp(a);
710 BOOST_CHECK_CLOSE_FRACTION(a, Real(exp(Real(3))), tol);
711 a = 3;
712 a = log(a);
713 BOOST_CHECK_CLOSE_FRACTION(a, Real(log(Real(3))), tol);
714 a = 3;
715 a = log10(a);
716 BOOST_CHECK_CLOSE_FRACTION(a, Real(log10(Real(3))), tol);
717
718 a = 0.5;
719 a = sin(a);
720 BOOST_CHECK_CLOSE_FRACTION(a, Real(sin(Real(0.5))), tol);
721 a = 0.5;
722 a = cos(a);
723 BOOST_CHECK_CLOSE_FRACTION(a, Real(cos(Real(0.5))), tol);
724 a = 0.5;
725 a = tan(a);
726 BOOST_CHECK_CLOSE_FRACTION(a, Real(tan(Real(0.5))), tol);
727 a = 0.5;
728 a = asin(a);
729 BOOST_CHECK_CLOSE_FRACTION(a, Real(asin(Real(0.5))), tol);
730 a = 0.5;
731 a = acos(a);
732 BOOST_CHECK_CLOSE_FRACTION(a, Real(acos(Real(0.5))), tol);
733 a = 0.5;
734 a = atan(a);
735 BOOST_CHECK_CLOSE_FRACTION(a, Real(atan(Real(0.5))), tol);
736 a = 0.5;
737 a = sinh(a);
738 BOOST_CHECK_CLOSE_FRACTION(a, Real(sinh(Real(0.5))), tol);
739 a = 0.5;
740 a = cosh(a);
741 BOOST_CHECK_CLOSE_FRACTION(a, Real(cosh(Real(0.5))), tol);
742 a = 0.5;
743 a = tanh(a);
744 BOOST_CHECK_CLOSE_FRACTION(a, Real(tanh(Real(0.5))), tol);
745 a = 4;
746 b = 2;
747 a = fmod(a, b);
748 BOOST_CHECK_CLOSE_FRACTION(a, Real(fmod(Real(4), Real(2))), tol);
749 a = 4;
750 b = fmod(a, b);
751 BOOST_CHECK_CLOSE_FRACTION(b, Real(fmod(Real(4), Real(2))), tol);
752 b = 2;
753 a = atan2(a, b);
754 BOOST_CHECK_CLOSE_FRACTION(a, Real(atan2(Real(4), Real(2))), tol);
755 a = 4;
756 b = atan2(a, b);
757 BOOST_CHECK_CLOSE_FRACTION(b, Real(atan2(Real(4), Real(2))), tol);
758 }
759
760 template <class T, class U>
compare_NaNs(const T & a,const U & b)761 void compare_NaNs(const T& a, const U& b)
762 {
763 BOOST_CHECK_EQUAL(a == b, false);
764 BOOST_CHECK_EQUAL(a != b, true);
765 BOOST_CHECK_EQUAL(a <= b, false);
766 BOOST_CHECK_EQUAL(a >= b, false);
767 BOOST_CHECK_EQUAL(a > b, false);
768 BOOST_CHECK_EQUAL(a < b, false);
769 //
770 // Again where LHS may be an expression template:
771 //
772 BOOST_CHECK_EQUAL(1 * a == b, false);
773 BOOST_CHECK_EQUAL(1 * a != b, true);
774 BOOST_CHECK_EQUAL(1 * a <= b, false);
775 BOOST_CHECK_EQUAL(1 * a >= b, false);
776 BOOST_CHECK_EQUAL(1 * a > b, false);
777 BOOST_CHECK_EQUAL(1 * a < b, false);
778 //
779 // Again where RHS may be an expression template:
780 //
781 BOOST_CHECK_EQUAL(a == b * 1, false);
782 BOOST_CHECK_EQUAL(a != b * 1, true);
783 BOOST_CHECK_EQUAL(a <= b * 1, false);
784 BOOST_CHECK_EQUAL(a >= b * 1, false);
785 BOOST_CHECK_EQUAL(a > b * 1, false);
786 BOOST_CHECK_EQUAL(a < b * 1, false);
787 //
788 // Again where LHS and RHS may be an expression templates:
789 //
790 BOOST_CHECK_EQUAL(1 * a == b * 1, false);
791 BOOST_CHECK_EQUAL(1 * a != b * 1, true);
792 BOOST_CHECK_EQUAL(1 * a <= b * 1, false);
793 BOOST_CHECK_EQUAL(1 * a >= b * 1, false);
794 BOOST_CHECK_EQUAL(1 * a > b * 1, false);
795 BOOST_CHECK_EQUAL(1 * a < b * 1, false);
796 }
797
798 template <class Real, class T>
test_float_ops(const T &)799 void test_float_ops(const T&){}
800
801 template <class Real>
test_float_ops(const boost::mpl::int_<boost::multiprecision::number_kind_floating_point> &)802 void test_float_ops(const boost::mpl::int_<boost::multiprecision::number_kind_floating_point>&)
803 {
804 BOOST_CHECK_EQUAL(abs(Real(2)) , 2);
805 BOOST_CHECK_EQUAL(abs(Real(-2)) , 2);
806 BOOST_CHECK_EQUAL(fabs(Real(2)) , 2);
807 BOOST_CHECK_EQUAL(fabs(Real(-2)) , 2);
808 BOOST_CHECK_EQUAL(floor(Real(5) / 2) , 2);
809 BOOST_CHECK_EQUAL(ceil(Real(5) / 2) , 3);
810 BOOST_CHECK_EQUAL(floor(Real(-5) / 2) , -3);
811 BOOST_CHECK_EQUAL(ceil(Real(-5) / 2) , -2);
812 BOOST_CHECK_EQUAL(trunc(Real(5) / 2) , 2);
813 BOOST_CHECK_EQUAL(trunc(Real(-5) / 2) , -2);
814 //
815 // ldexp and frexp, these pretty much have to be implemented by each backend:
816 //
817 BOOST_CHECK_EQUAL(ldexp(Real(2), 5) , 64);
818 BOOST_CHECK_EQUAL(ldexp(Real(2), -5) , Real(2) / 32);
819 Real v(512);
820 int exponent;
821 Real r = frexp(v, &exponent);
822 BOOST_CHECK_EQUAL(r , 0.5);
823 BOOST_CHECK_EQUAL(exponent , 10);
824 BOOST_CHECK_EQUAL(v , 512);
825 v = 1 / v;
826 r = frexp(v, &exponent);
827 BOOST_CHECK_EQUAL(r , 0.5);
828 BOOST_CHECK_EQUAL(exponent , -8);
829 typedef typename Real::backend_type::exponent_type e_type;
830 BOOST_CHECK_EQUAL(ldexp(Real(2), e_type(5)) , 64);
831 BOOST_CHECK_EQUAL(ldexp(Real(2), e_type(-5)) , Real(2) / 32);
832 v = 512;
833 e_type exp2;
834 r = frexp(v, &exp2);
835 BOOST_CHECK_EQUAL(r , 0.5);
836 BOOST_CHECK_EQUAL(exp2 , 10);
837 BOOST_CHECK_EQUAL(v , 512);
838 v = 1 / v;
839 r = frexp(v, &exp2);
840 BOOST_CHECK_EQUAL(r , 0.5);
841 BOOST_CHECK_EQUAL(exp2 , -8);
842 //
843 // scalbn and logb, these are the same as ldexp and frexp unless the radix is
844 // something other than 2:
845 //
846 if(std::numeric_limits<Real>::is_specialized && std::numeric_limits<Real>::radix)
847 {
848 BOOST_CHECK_EQUAL(scalbn(Real(2), 5), 2 * pow(double(std::numeric_limits<Real>::radix), 5));
849 BOOST_CHECK_EQUAL(scalbn(Real(2), -5), Real(2) / pow(double(std::numeric_limits<Real>::radix), 5));
850 Real v(512);
851 int exponent;
852 Real r;
853 exponent = ilogb(v);
854 r = scalbn(v, -exponent);
855 BOOST_CHECK(r >= 1);
856 BOOST_CHECK(r < std::numeric_limits<Real>::radix);
857 BOOST_CHECK_EQUAL(exponent, logb(v));
858 BOOST_CHECK_EQUAL(v, scalbn(r, exponent));
859 v = 1 / v;
860 exponent = ilogb(v);
861 r = scalbn(v, -exponent);
862 BOOST_CHECK(r >= 1);
863 BOOST_CHECK(r < std::numeric_limits<Real>::radix);
864 BOOST_CHECK_EQUAL(exponent, logb(v));
865 BOOST_CHECK_EQUAL(v, scalbn(r, exponent));
866 }
867 //
868 // pow and exponent:
869 //
870 v = 3.25;
871 r = pow(v, 0);
872 BOOST_CHECK_EQUAL(r , 1);
873 r = pow(v, 1);
874 BOOST_CHECK_EQUAL(r , 3.25);
875 r = pow(v, 2);
876 BOOST_CHECK_EQUAL(r , boost::math::pow<2>(3.25));
877 r = pow(v, 3);
878 BOOST_CHECK_EQUAL(r , boost::math::pow<3>(3.25));
879 r = pow(v, 4);
880 BOOST_CHECK_EQUAL(r , boost::math::pow<4>(3.25));
881 r = pow(v, 5);
882 BOOST_CHECK_EQUAL(r , boost::math::pow<5>(3.25));
883 r = pow(v, 6);
884 BOOST_CHECK_EQUAL(r , boost::math::pow<6>(3.25));
885 r = pow(v, 25);
886 BOOST_CHECK_EQUAL(r , boost::math::pow<25>(Real(3.25)));
887 //
888 // Things that are expected errors:
889 //
890 BOOST_CHECK_THROW(Real("3.14L"), std::runtime_error);
891 if(std::numeric_limits<Real>::is_specialized)
892 {
893 if(std::numeric_limits<Real>::has_infinity)
894 {
895 BOOST_CHECK((boost::math::isinf)(Real(20) / 0u));
896 }
897 else
898 {
899 BOOST_CHECK_THROW(Real(Real(20) / 0u), std::overflow_error);
900 }
901 }
902 //
903 // Comparisons of NaN's should always fail:
904 //
905 if(std::numeric_limits<Real>::has_quiet_NaN)
906 {
907 r = v = std::numeric_limits<Real>::quiet_NaN();
908 compare_NaNs(r, v);
909 v = 0;
910 compare_NaNs(r, v);
911 r.swap(v);
912 compare_NaNs(r, v);
913 //
914 // Conmpare NaN to int:
915 //
916 compare_NaNs(v, 0);
917 compare_NaNs(0, v);
918 //
919 // Compare to floats:
920 //
921 compare_NaNs(v, 0.5);
922 compare_NaNs(0.5, v);
923 if(std::numeric_limits<double>::has_quiet_NaN)
924 {
925 compare_NaNs(r, std::numeric_limits<double>::quiet_NaN());
926 compare_NaNs(std::numeric_limits<double>::quiet_NaN(), r);
927 }
928 }
929
930 test_float_funcs<Real>(boost::mpl::bool_<std::numeric_limits<Real>::is_specialized>());
931 }
932
933 template <class T>
934 struct lexical_cast_target_type
935 {
936 typedef typename boost::mpl::if_<
937 boost::is_signed<T>,
938 boost::intmax_t,
939 typename boost::mpl::if_<
940 boost::is_unsigned<T>,
941 boost::uintmax_t,
942 T
943 >::type
944 >::type type;
945 };
946
947 template <class Real, class Num>
test_negative_mixed_minmax(boost::mpl::true_ const &)948 void test_negative_mixed_minmax(boost::mpl::true_ const&)
949 {
950 if(!std::numeric_limits<Real>::is_bounded || (std::numeric_limits<Real>::digits >= std::numeric_limits<Num>::digits))
951 {
952 Real mx1((std::numeric_limits<Num>::max)() - 1);
953 ++mx1;
954 Real mx2((std::numeric_limits<Num>::max)());
955 BOOST_CHECK_EQUAL(mx1, mx2);
956 mx1 = (std::numeric_limits<Num>::max)() - 1;
957 ++mx1;
958 mx2 = (std::numeric_limits<Num>::max)();
959 BOOST_CHECK_EQUAL(mx1, mx2);
960
961 if(!std::numeric_limits<Real>::is_bounded || (std::numeric_limits<Real>::digits > std::numeric_limits<Num>::digits))
962 {
963 Real mx3((std::numeric_limits<Num>::min)() + 1);
964 --mx3;
965 Real mx4((std::numeric_limits<Num>::min)());
966 BOOST_CHECK_EQUAL(mx3, mx4);
967 mx3 = (std::numeric_limits<Num>::min)() + 1;
968 --mx3;
969 mx4 = (std::numeric_limits<Num>::min)();
970 BOOST_CHECK_EQUAL(mx3, mx4);
971 }
972 }
973 }
974 template <class Real, class Num>
test_negative_mixed_minmax(boost::mpl::false_ const &)975 void test_negative_mixed_minmax(boost::mpl::false_ const&)
976 {
977 }
978
979 template <class Real, class Num>
test_negative_mixed(boost::mpl::true_ const &)980 void test_negative_mixed(boost::mpl::true_ const&)
981 {
982 typedef typename lexical_cast_target_type<Num>::type target_type;
983 typedef typename boost::mpl::if_<
984 boost::is_convertible<Num, Real>,
985 typename boost::mpl::if_c<boost::is_integral<Num>::value && (sizeof(Num) < sizeof(int)), int, Num>::type,
986 Real
987 >::type cast_type;
988 typedef typename boost::mpl::if_<
989 boost::is_convertible<Num, Real>,
990 Num,
991 Real
992 >::type simple_cast_type;
993 std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name() << " and " << typeid(Num).name() << std::endl;
994 static const int left_shift = std::numeric_limits<Num>::digits - 1;
995 Num n1 = -static_cast<Num>(1uLL << ((left_shift < 63) && (left_shift > 0) ? left_shift : 10));
996 Num n2 = -1;
997 Num n3 = 0;
998 Num n4 = -20;
999 Num n5 = -8;
1000
1001 test_comparisons<Real>(n1, n2, boost::is_convertible<Num, Real>());
1002 test_comparisons<Real>(n1, n3, boost::is_convertible<Num, Real>());
1003 test_comparisons<Real>(n3, n1, boost::is_convertible<Num, Real>());
1004 test_comparisons<Real>(n2, n1, boost::is_convertible<Num, Real>());
1005 test_comparisons<Real>(n1, n1, boost::is_convertible<Num, Real>());
1006 test_comparisons<Real>(n3, n3, boost::is_convertible<Num, Real>());
1007
1008 // Default construct:
1009 BOOST_CHECK_EQUAL(Real(n1) , static_cast<cast_type>(n1));
1010 BOOST_CHECK_EQUAL(Real(n2) , static_cast<cast_type>(n2));
1011 BOOST_CHECK_EQUAL(Real(n3) , static_cast<cast_type>(n3));
1012 BOOST_CHECK_EQUAL(Real(n4) , static_cast<cast_type>(n4));
1013 BOOST_CHECK_EQUAL(static_cast<cast_type>(n1) , Real(n1));
1014 BOOST_CHECK_EQUAL(static_cast<cast_type>(n2) , Real(n2));
1015 BOOST_CHECK_EQUAL(static_cast<cast_type>(n3) , Real(n3));
1016 BOOST_CHECK_EQUAL(static_cast<cast_type>(n4) , Real(n4));
1017 BOOST_CHECK_EQUAL(Real(n1).template convert_to<Num>() , n1);
1018 BOOST_CHECK_EQUAL(Real(n2).template convert_to<Num>() , n2);
1019 BOOST_CHECK_EQUAL(Real(n3).template convert_to<Num>() , n3);
1020 BOOST_CHECK_EQUAL(Real(n4).template convert_to<Num>() , n4);
1021 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
1022 BOOST_CHECK_EQUAL(static_cast<Num>(Real(n1)) , n1);
1023 BOOST_CHECK_EQUAL(static_cast<Num>(Real(n2)) , n2);
1024 BOOST_CHECK_EQUAL(static_cast<Num>(Real(n3)) , n3);
1025 BOOST_CHECK_EQUAL(static_cast<Num>(Real(n4)) , n4);
1026 #endif
1027 #if defined(TEST_MPFR)
1028 Num tol = 10 * std::numeric_limits<Num>::epsilon();
1029 #else
1030 Num tol = 0;
1031 #endif
1032 std::ios_base::fmtflags f = boost::is_floating_point<Num>::value ? std::ios_base::scientific : std::ios_base::fmtflags(0);
1033 int digits_to_print = boost::is_floating_point<Num>::value && std::numeric_limits<Num>::is_specialized
1034 ? std::numeric_limits<Num>::digits10 + 5 : 0;
1035 if(std::numeric_limits<target_type>::digits <= std::numeric_limits<Real>::digits)
1036 {
1037 BOOST_CHECK_CLOSE(n1, checked_lexical_cast<target_type>(Real(n1).str(digits_to_print, f)), tol);
1038 }
1039 BOOST_CHECK_CLOSE(n2, checked_lexical_cast<target_type>(Real(n2).str(digits_to_print, f)), 0);
1040 BOOST_CHECK_CLOSE(n3, checked_lexical_cast<target_type>(Real(n3).str(digits_to_print, f)), 0);
1041 BOOST_CHECK_CLOSE(n4, checked_lexical_cast<target_type>(Real(n4).str(digits_to_print, f)), 0);
1042 // Assignment:
1043 Real r(0);
1044 BOOST_CHECK(r != static_cast<cast_type>(n1));
1045 r = static_cast<simple_cast_type>(n1);
1046 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n1));
1047 r = static_cast<simple_cast_type>(n2);
1048 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n2));
1049 r = static_cast<simple_cast_type>(n3);
1050 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n3));
1051 r = static_cast<simple_cast_type>(n4);
1052 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4));
1053 // Addition:
1054 r = static_cast<simple_cast_type>(n2);
1055 BOOST_CHECK_EQUAL(r + static_cast<simple_cast_type>(n4) , static_cast<cast_type>(n2 + n4));
1056 BOOST_CHECK_EQUAL(Real(r + static_cast<simple_cast_type>(n4)) , static_cast<cast_type>(n2 + n4));
1057 r += static_cast<simple_cast_type>(n4);
1058 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n2 + n4));
1059 // subtraction:
1060 r = static_cast<simple_cast_type>(n4);
1061 BOOST_CHECK_EQUAL(r - static_cast<simple_cast_type>(n5) , static_cast<cast_type>(n4 - n5));
1062 BOOST_CHECK_EQUAL(Real(r - static_cast<simple_cast_type>(n5)) , static_cast<cast_type>(n4 - n5));
1063 r -= static_cast<simple_cast_type>(n5);
1064 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4 - n5));
1065 // Multiplication:
1066 r = static_cast<simple_cast_type>(n2);
1067 BOOST_CHECK_EQUAL(r * static_cast<simple_cast_type>(n4) , static_cast<cast_type>(n2 * n4));
1068 BOOST_CHECK_EQUAL(Real(r * static_cast<simple_cast_type>(n4)) , static_cast<cast_type>(n2 * n4));
1069 r *= static_cast<simple_cast_type>(n4);
1070 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n2 * n4));
1071 // Division:
1072 r = static_cast<simple_cast_type>(n1);
1073 BOOST_CHECK_EQUAL(r / static_cast<simple_cast_type>(n5) , static_cast<cast_type>(n1 / n5));
1074 BOOST_CHECK_EQUAL(Real(r / static_cast<simple_cast_type>(n5)) , static_cast<cast_type>(n1 / n5));
1075 r /= static_cast<simple_cast_type>(n5);
1076 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n1 / n5));
1077 //
1078 // Extra cases for full coverage:
1079 //
1080 r = Real(n4) + static_cast<simple_cast_type>(n5);
1081 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4 + n5));
1082 r = static_cast<simple_cast_type>(n4) + Real(n5);
1083 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4 + n5));
1084 r = Real(n4) - static_cast<simple_cast_type>(n5);
1085 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4 - n5));
1086 r = static_cast<simple_cast_type>(n4) - Real(n5);
1087 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4 - n5));
1088 r = static_cast<simple_cast_type>(n4) * Real(n5);
1089 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4 * n5));
1090 r = static_cast<cast_type>(4 * n4) / Real(4);
1091 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4));
1092
1093 Real a, b, c;
1094 a = 20;
1095 b = 30;
1096 c = -a + b;
1097 BOOST_CHECK_EQUAL(c , 10);
1098 c = b + -a;
1099 BOOST_CHECK_EQUAL(c , 10);
1100 n4 = 30;
1101 c = -a + static_cast<cast_type>(n4);
1102 BOOST_CHECK_EQUAL(c , 10);
1103 c = static_cast<cast_type>(n4) + -a;
1104 BOOST_CHECK_EQUAL(c , 10);
1105 c = -a + -b;
1106 BOOST_CHECK_EQUAL(c , -50);
1107 n4 = 4;
1108 c = -(a + b) + static_cast<cast_type>(n4);
1109 BOOST_CHECK_EQUAL(c , -50+4);
1110 n4 = 50;
1111 c = (a + b) - static_cast<cast_type>(n4);
1112 BOOST_CHECK_EQUAL(c , 0);
1113 c = (a + b) - static_cast<cast_type>(n4);
1114 BOOST_CHECK_EQUAL(c , 0);
1115 c = a - -(b + static_cast<cast_type>(n4));
1116 BOOST_CHECK_EQUAL(c , 20 - -(30 + 50));
1117 c = -(b + static_cast<cast_type>(n4)) - a;
1118 BOOST_CHECK_EQUAL(c , -(30 + 50) - 20);
1119 c = a - -b;
1120 BOOST_CHECK_EQUAL(c , 50);
1121 c = -a - b;
1122 BOOST_CHECK_EQUAL(c , -50);
1123 c = -a - static_cast<cast_type>(n4);
1124 BOOST_CHECK_EQUAL(c , -20 - 50);
1125 c = static_cast<cast_type>(n4) - -a;
1126 BOOST_CHECK_EQUAL(c , 50 + 20);
1127 c = -(a + b) - Real(n4);
1128 BOOST_CHECK_EQUAL(c , -(20 + 30) - 50);
1129 c = static_cast<cast_type>(n4) - (a + b);
1130 BOOST_CHECK_EQUAL(c , 0);
1131 c = (a + b) * static_cast<cast_type>(n4);
1132 BOOST_CHECK_EQUAL(c , 50 * 50);
1133 c = static_cast<cast_type>(n4) * (a + b);
1134 BOOST_CHECK_EQUAL(c , 50 * 50);
1135 c = a * -(b + static_cast<cast_type>(n4));
1136 BOOST_CHECK_EQUAL(c , 20 * -(30 + 50));
1137 c = -(b + static_cast<cast_type>(n4)) * a;
1138 BOOST_CHECK_EQUAL(c , 20 * -(30 + 50));
1139 c = a * -b;
1140 BOOST_CHECK_EQUAL(c , 20 * -30);
1141 c = -a * b;
1142 BOOST_CHECK_EQUAL(c , 20 * -30);
1143 c = -a * static_cast<cast_type>(n4);
1144 BOOST_CHECK_EQUAL(c , -20 * 50);
1145 c = static_cast<cast_type>(n4) * -a;
1146 BOOST_CHECK_EQUAL(c , -20 * 50);
1147 c = -(a + b) + a;
1148 BOOST_CHECK(-50 + 20);
1149 c = static_cast<cast_type>(n4) - (a + b);
1150 BOOST_CHECK_EQUAL(c , 0);
1151 Real d = 10;
1152 c = (a + b) / d;
1153 BOOST_CHECK_EQUAL(c , 5);
1154 c = (a + b) / (d + 0);
1155 BOOST_CHECK_EQUAL(c , 5);
1156 c = (a + b) / static_cast<cast_type>(n4);
1157 BOOST_CHECK_EQUAL(c , 1);
1158 c = static_cast<cast_type>(n4) / (a + b);
1159 BOOST_CHECK_EQUAL(c , 1);
1160 d = 50;
1161 c = d / -(a + b);
1162 BOOST_CHECK_EQUAL(c , -1);
1163 c = -(a + b) / d;
1164 BOOST_CHECK_EQUAL(c , -1);
1165 d = 2;
1166 c = a / -d;
1167 BOOST_CHECK_EQUAL(c , 20 / -2);
1168 c = -a / d;
1169 BOOST_CHECK_EQUAL(c , 20 / -2);
1170 d = 50;
1171 c = -d / static_cast<cast_type>(n4);
1172 BOOST_CHECK_EQUAL(c , -1);
1173 c = static_cast<cast_type>(n4) / -d;
1174 BOOST_CHECK_EQUAL(c , -1);
1175 c = static_cast<cast_type>(n4) + a;
1176 BOOST_CHECK_EQUAL(c , 70);
1177 c = static_cast<cast_type>(n4) - a;
1178 BOOST_CHECK_EQUAL(c , 30);
1179 c = static_cast<cast_type>(n4) * a;
1180 BOOST_CHECK_EQUAL(c , 50 * 20);
1181
1182 n1 = -2;
1183 n2 = -3;
1184 n3 = -4;
1185 a = static_cast<cast_type>(n1);
1186 b = static_cast<cast_type>(n2);
1187 c = static_cast<cast_type>(n3);
1188 d = a + b * c;
1189 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1190 d = static_cast<cast_type>(n1) + b * c;
1191 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1192 d = a + static_cast<cast_type>(n2) * c;
1193 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1194 d = a + b * static_cast<cast_type>(n3);
1195 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1196 d = static_cast<cast_type>(n1) + static_cast<cast_type>(n2) * c;
1197 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1198 d = static_cast<cast_type>(n1) + b * static_cast<cast_type>(n3);
1199 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1200 a += static_cast<cast_type>(n2) * c;
1201 BOOST_CHECK_EQUAL(a , -2 + -3 * -4);
1202 a = static_cast<cast_type>(n1);
1203 a += b * static_cast<cast_type>(n3);
1204 BOOST_CHECK_EQUAL(a , -2 + -3 * -4);
1205 a = static_cast<cast_type>(n1);
1206
1207 d = b * c + a;
1208 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1209 d = b * c + static_cast<cast_type>(n1);
1210 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1211 d = static_cast<cast_type>(n2) * c + a;
1212 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1213 d = b * static_cast<cast_type>(n3) + a;
1214 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1215 d = static_cast<cast_type>(n2) * c + static_cast<cast_type>(n1);
1216 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1217 d = b * static_cast<cast_type>(n3) + static_cast<cast_type>(n1);
1218 BOOST_CHECK_EQUAL(d , -2 + -3 * -4);
1219
1220 a = -20;
1221 d = a - b * c;
1222 BOOST_CHECK_EQUAL(d , -20 - -3 * -4);
1223 n1 = -20;
1224 d = static_cast<cast_type>(n1) - b * c;
1225 BOOST_CHECK_EQUAL(d , -20 - -3 * -4);
1226 d = a - static_cast<cast_type>(n2) * c;
1227 BOOST_CHECK_EQUAL(d , -20 - -3 * -4);
1228 d = a - b * static_cast<cast_type>(n3);
1229 BOOST_CHECK_EQUAL(d , -20 - -3 * -4);
1230 d = static_cast<cast_type>(n1) - static_cast<cast_type>(n2) * c;
1231 BOOST_CHECK_EQUAL(d , -20 - -3 * -4);
1232 d = static_cast<cast_type>(n1) - b * static_cast<cast_type>(n3);
1233 BOOST_CHECK_EQUAL(d , -20 - -3 * -4);
1234 a -= static_cast<cast_type>(n2) * c;
1235 BOOST_CHECK_EQUAL(a , -20 - -3 * -4);
1236 a = static_cast<cast_type>(n1);
1237 a -= b * static_cast<cast_type>(n3);
1238 BOOST_CHECK_EQUAL(a , -20 - -3 * -4);
1239
1240 a = -2;
1241 d = b * c - a;
1242 BOOST_CHECK_EQUAL(d , -3 * -4 - -2);
1243 n1 = -2;
1244 d = b * c - static_cast<cast_type>(n1);
1245 BOOST_CHECK_EQUAL(d , -3 * -4 - -2);
1246 d = static_cast<cast_type>(n2) * c - a;
1247 BOOST_CHECK_EQUAL(d , -3 * -4 - -2);
1248 d = b * static_cast<cast_type>(n3) - a;
1249 BOOST_CHECK_EQUAL(d , -3 * -4 - -2);
1250 d = static_cast<cast_type>(n2) * c - static_cast<cast_type>(n1);
1251 BOOST_CHECK_EQUAL(d , -3 * -4 - -2);
1252 d = b * static_cast<cast_type>(n3) - static_cast<cast_type>(n1);
1253 BOOST_CHECK_EQUAL(d , -3 * -4 - -2);
1254 //
1255 // Conversion from min and max values:
1256 //
1257 test_negative_mixed_minmax<Real, Num>(boost::mpl::bool_<std::numeric_limits<Real>::is_integer && std::numeric_limits<Num>::is_integer>());
1258 }
1259
1260 template <class Real, class Num>
test_negative_mixed(boost::mpl::false_ const &)1261 void test_negative_mixed(boost::mpl::false_ const&)
1262 {
1263 }
1264
1265 template <class Real, class Num>
test_mixed(const boost::mpl::false_ &)1266 void test_mixed(const boost::mpl::false_&)
1267 {
1268 }
1269
1270 template <class Real, class Num>
test_mixed(const boost::mpl::true_ &)1271 void test_mixed(const boost::mpl::true_&)
1272 {
1273 typedef typename lexical_cast_target_type<Num>::type target_type;
1274 typedef typename boost::mpl::if_<
1275 boost::is_convertible<Num, Real>,
1276 typename boost::mpl::if_c<boost::is_integral<Num>::value && (sizeof(Num) < sizeof(int)), int, Num>::type,
1277 Real
1278 >::type cast_type;
1279 typedef typename boost::mpl::if_<
1280 boost::is_convertible<Num, Real>,
1281 Num,
1282 Real
1283 >::type simple_cast_type;
1284
1285 if(std::numeric_limits<Real>::is_specialized && std::numeric_limits<Real>::is_bounded && std::numeric_limits<Real>::digits < std::numeric_limits<Num>::digits)
1286 return;
1287
1288 std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name() << " and " << typeid(Num).name() << std::endl;
1289 static const int left_shift = std::numeric_limits<Num>::digits - 1;
1290 Num n1 = static_cast<Num>(1uLL << ((left_shift < 63) && (left_shift > 0) ? left_shift : 10));
1291 Num n2 = 1;
1292 Num n3 = 0;
1293 Num n4 = 20;
1294 Num n5 = 8;
1295
1296 test_comparisons<Real>(n1, n2, boost::is_convertible<Num, Real>());
1297 test_comparisons<Real>(n1, n3, boost::is_convertible<Num, Real>());
1298 test_comparisons<Real>(n1, n1, boost::is_convertible<Num, Real>());
1299 test_comparisons<Real>(n3, n1, boost::is_convertible<Num, Real>());
1300 test_comparisons<Real>(n2, n1, boost::is_convertible<Num, Real>());
1301 test_comparisons<Real>(n3, n3, boost::is_convertible<Num, Real>());
1302
1303 // Default construct:
1304 BOOST_CHECK_EQUAL(Real(n1) , static_cast<cast_type>(n1));
1305 BOOST_CHECK_EQUAL(Real(n2) , static_cast<cast_type>(n2));
1306 BOOST_CHECK_EQUAL(Real(n3) , static_cast<cast_type>(n3));
1307 BOOST_CHECK_EQUAL(Real(n4) , static_cast<cast_type>(n4));
1308 BOOST_CHECK_EQUAL(Real(n1).template convert_to<Num>() , n1);
1309 BOOST_CHECK_EQUAL(Real(n2).template convert_to<Num>() , n2);
1310 BOOST_CHECK_EQUAL(Real(n3).template convert_to<Num>() , n3);
1311 BOOST_CHECK_EQUAL(Real(n4).template convert_to<Num>() , n4);
1312 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
1313 BOOST_CHECK_EQUAL(static_cast<Num>(Real(n1)) , n1);
1314 BOOST_CHECK_EQUAL(static_cast<Num>(Real(n2)) , n2);
1315 BOOST_CHECK_EQUAL(static_cast<Num>(Real(n3)) , n3);
1316 BOOST_CHECK_EQUAL(static_cast<Num>(Real(n4)) , n4);
1317 #endif
1318 BOOST_CHECK_EQUAL(static_cast<cast_type>(n1) , Real(n1));
1319 BOOST_CHECK_EQUAL(static_cast<cast_type>(n2) , Real(n2));
1320 BOOST_CHECK_EQUAL(static_cast<cast_type>(n3) , Real(n3));
1321 BOOST_CHECK_EQUAL(static_cast<cast_type>(n4) , Real(n4));
1322 #if defined(TEST_MPFR)
1323 Num tol = 10 * std::numeric_limits<Num>::epsilon();
1324 #else
1325 Num tol = 0;
1326 #endif
1327 std::ios_base::fmtflags f = boost::is_floating_point<Num>::value ? std::ios_base::scientific : std::ios_base::fmtflags(0);
1328 int digits_to_print = boost::is_floating_point<Num>::value && std::numeric_limits<Num>::is_specialized
1329 ? std::numeric_limits<Num>::digits10 + 5 : 0;
1330 if(std::numeric_limits<target_type>::digits <= std::numeric_limits<Real>::digits)
1331 {
1332 BOOST_CHECK_CLOSE(n1, checked_lexical_cast<target_type>(Real(n1).str(digits_to_print, f)), tol);
1333 }
1334 BOOST_CHECK_CLOSE(n2, checked_lexical_cast<target_type>(Real(n2).str(digits_to_print, f)), 0);
1335 BOOST_CHECK_CLOSE(n3, checked_lexical_cast<target_type>(Real(n3).str(digits_to_print, f)), 0);
1336 BOOST_CHECK_CLOSE(n4, checked_lexical_cast<target_type>(Real(n4).str(digits_to_print, f)), 0);
1337 // Assignment:
1338 Real r(0);
1339 BOOST_CHECK(r != static_cast<cast_type>(n1));
1340 r = static_cast<simple_cast_type>(n1);
1341 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n1));
1342 r = static_cast<simple_cast_type>(n2);
1343 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n2));
1344 r = static_cast<simple_cast_type>(n3);
1345 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n3));
1346 r = static_cast<simple_cast_type>(n4);
1347 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4));
1348 // Addition:
1349 r = static_cast<simple_cast_type>(n2);
1350 BOOST_CHECK_EQUAL(r + static_cast<simple_cast_type>(n4) , static_cast<cast_type>(n2 + n4));
1351 BOOST_CHECK_EQUAL(Real(r + static_cast<simple_cast_type>(n4)) , static_cast<cast_type>(n2 + n4));
1352 r += static_cast<simple_cast_type>(n4);
1353 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n2 + n4));
1354 // subtraction:
1355 r = static_cast<simple_cast_type>(n4);
1356 BOOST_CHECK_EQUAL(r - static_cast<simple_cast_type>(n5) , static_cast<cast_type>(n4 - n5));
1357 BOOST_CHECK_EQUAL(Real(r - static_cast<simple_cast_type>(n5)) , static_cast<cast_type>(n4 - n5));
1358 r -= static_cast<simple_cast_type>(n5);
1359 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4 - n5));
1360 // Multiplication:
1361 r = static_cast<simple_cast_type>(n2);
1362 BOOST_CHECK_EQUAL(r * static_cast<simple_cast_type>(n4) , static_cast<cast_type>(n2 * n4));
1363 BOOST_CHECK_EQUAL(Real(r * static_cast<simple_cast_type>(n4)) , static_cast<cast_type>(n2 * n4));
1364 r *= static_cast<simple_cast_type>(n4);
1365 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n2 * n4));
1366 // Division:
1367 r = static_cast<simple_cast_type>(n1);
1368 BOOST_CHECK_EQUAL(r / static_cast<simple_cast_type>(n5) , static_cast<cast_type>(n1 / n5));
1369 BOOST_CHECK_EQUAL(Real(r / static_cast<simple_cast_type>(n5)) , static_cast<cast_type>(n1 / n5));
1370 r /= static_cast<simple_cast_type>(n5);
1371 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n1 / n5));
1372 //
1373 // special cases for full coverage:
1374 //
1375 r = static_cast<simple_cast_type>(n5) + Real(n4);
1376 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4 + n5));
1377 r = static_cast<simple_cast_type>(n4) - Real(n5);
1378 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4 - n5));
1379 r = static_cast<simple_cast_type>(n4) * Real(n5);
1380 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4 * n5));
1381 r = static_cast<cast_type>(4 * n4) / Real(4);
1382 BOOST_CHECK_EQUAL(r , static_cast<cast_type>(n4));
1383
1384 typedef boost::mpl::bool_<
1385 (!std::numeric_limits<Num>::is_specialized || std::numeric_limits<Num>::is_signed)
1386 && (!std::numeric_limits<Real>::is_specialized || std::numeric_limits<Real>::is_signed)> signed_tag;
1387
1388 test_negative_mixed<Real, Num>(signed_tag());
1389
1390 n1 = 2;
1391 n2 = 3;
1392 n3 = 4;
1393 Real a(n1), b(n2), c(n3), d;
1394 d = a + b * c;
1395 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1396 d = static_cast<cast_type>(n1) + b * c;
1397 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1398 d = a + static_cast<cast_type>(n2) * c;
1399 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1400 d = a + b * static_cast<cast_type>(n3);
1401 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1402 d = static_cast<cast_type>(n1) + static_cast<cast_type>(n2) * c;
1403 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1404 d = static_cast<cast_type>(n1) + b * static_cast<cast_type>(n3);
1405 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1406 a += static_cast<cast_type>(n2) * c;
1407 BOOST_CHECK_EQUAL(a , 2 + 3 * 4);
1408 a = static_cast<cast_type>(n1);
1409 a += b * static_cast<cast_type>(n3);
1410 BOOST_CHECK_EQUAL(a , 2 + 3 * 4);
1411 a = static_cast<cast_type>(n1);
1412
1413 d = b * c + a;
1414 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1415 d = b * c + static_cast<cast_type>(n1);
1416 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1417 d = static_cast<cast_type>(n2) * c + a;
1418 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1419 d = b * static_cast<cast_type>(n3) + a;
1420 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1421 d = static_cast<cast_type>(n2) * c + static_cast<cast_type>(n1);
1422 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1423 d = b * static_cast<cast_type>(n3) + static_cast<cast_type>(n1);
1424 BOOST_CHECK_EQUAL(d , 2 + 3 * 4);
1425
1426 a = 20;
1427 d = a - b * c;
1428 BOOST_CHECK_EQUAL(d , 20 - 3 * 4);
1429 n1 = 20;
1430 d = static_cast<cast_type>(n1) - b * c;
1431 BOOST_CHECK_EQUAL(d , 20 - 3 * 4);
1432 d = a - static_cast<cast_type>(n2) * c;
1433 BOOST_CHECK_EQUAL(d , 20 - 3 * 4);
1434 d = a - b * static_cast<cast_type>(n3);
1435 BOOST_CHECK_EQUAL(d , 20 - 3 * 4);
1436 d = static_cast<cast_type>(n1) - static_cast<cast_type>(n2) * c;
1437 BOOST_CHECK_EQUAL(d , 20 - 3 * 4);
1438 d = static_cast<cast_type>(n1) - b * static_cast<cast_type>(n3);
1439 BOOST_CHECK_EQUAL(d , 20 - 3 * 4);
1440 a -= static_cast<cast_type>(n2) * c;
1441 BOOST_CHECK_EQUAL(a , 20 - 3 * 4);
1442 a = static_cast<cast_type>(n1);
1443 a -= b * static_cast<cast_type>(n3);
1444 BOOST_CHECK_EQUAL(a , 20 - 3 * 4);
1445
1446 a = 2;
1447 d = b * c - a;
1448 BOOST_CHECK_EQUAL(d , 3 * 4 - 2);
1449 n1 = 2;
1450 d = b * c - static_cast<cast_type>(n1);
1451 BOOST_CHECK_EQUAL(d , 3 * 4 - 2);
1452 d = static_cast<cast_type>(n2) * c - a;
1453 BOOST_CHECK_EQUAL(d , 3 * 4 - 2);
1454 d = b * static_cast<cast_type>(n3) - a;
1455 BOOST_CHECK_EQUAL(d , 3 * 4 - a);
1456 d = static_cast<cast_type>(n2) * c - static_cast<cast_type>(n1);
1457 BOOST_CHECK_EQUAL(d , 3 * 4 - 2);
1458 d = b * static_cast<cast_type>(n3) - static_cast<cast_type>(n1);
1459 BOOST_CHECK_EQUAL(d , 3 * 4 - 2);
1460 }
1461
1462 template <class Real>
test_members(Real)1463 void test_members(Real)
1464 {
1465 //
1466 // Test sign and zero functions:
1467 //
1468 Real a = 20;
1469 Real b = 30;
1470 BOOST_CHECK(a.sign() > 0);
1471 BOOST_CHECK(!a.is_zero());
1472 if(std::numeric_limits<Real>::is_signed)
1473 {
1474 a = -20;
1475 BOOST_CHECK(a.sign() < 0);
1476 BOOST_CHECK(!a.is_zero());
1477 }
1478 a = 0;
1479 BOOST_CHECK_EQUAL(a.sign() , 0);
1480 BOOST_CHECK(a.is_zero());
1481
1482 a = 20;
1483 b = 30;
1484 a.swap(b);
1485 BOOST_CHECK_EQUAL(a , 30);
1486 BOOST_CHECK_EQUAL(b , 20);
1487 }
1488
1489 template <class Real>
test_members(boost::rational<Real>)1490 void test_members(boost::rational<Real>)
1491 {
1492 }
1493
1494 template <class Real>
test_signed_ops(const boost::mpl::true_ &)1495 void test_signed_ops(const boost::mpl::true_&)
1496 {
1497 Real a(8);
1498 Real b(64);
1499 Real c(500);
1500 Real d(1024);
1501 Real ac;
1502 BOOST_CHECK_EQUAL(-a , -8);
1503 ac = a;
1504 ac = ac - b;
1505 BOOST_CHECK_EQUAL(ac , 8 - 64);
1506 ac = a;
1507 ac -= a + b;
1508 BOOST_CHECK_EQUAL(ac , -64);
1509 ac = a;
1510 ac -= b - a;
1511 BOOST_CHECK_EQUAL(ac , 16 - 64);
1512 ac = -a;
1513 BOOST_CHECK_EQUAL(ac , -8);
1514 ac = a;
1515 ac -= -a;
1516 BOOST_CHECK_EQUAL(ac , 16);
1517 ac = a;
1518 ac += -a;
1519 BOOST_CHECK_EQUAL(ac , 0);
1520 ac = b;
1521 ac /= -a;
1522 BOOST_CHECK_EQUAL(ac , -8);
1523 ac = a;
1524 ac *= -a;
1525 BOOST_CHECK_EQUAL(ac , -64);
1526 ac = a + -b;
1527 BOOST_CHECK_EQUAL(ac , 8 - 64);
1528 ac = -a + b;
1529 BOOST_CHECK_EQUAL(ac , -8+64);
1530 ac = -a + -b;
1531 BOOST_CHECK_EQUAL(ac , -72);
1532 ac = a + - + -b; // lots of unary operators!!
1533 BOOST_CHECK_EQUAL(ac , 72);
1534 test_conditional(Real(-a), -a);
1535 }
1536 template <class Real>
test_signed_ops(const boost::mpl::false_ &)1537 void test_signed_ops(const boost::mpl::false_&)
1538 {
1539 }
1540
1541 template <class Real>
test()1542 void test()
1543 {
1544 #if !defined(NO_MIXED_OPS) && !defined(SLOW_COMPILER)
1545 boost::multiprecision::is_number<Real> tag;
1546 test_mixed<Real, unsigned char>(tag);
1547 test_mixed<Real, signed char>(tag);
1548 test_mixed<Real, char>(tag);
1549 test_mixed<Real, short>(tag);
1550 test_mixed<Real, unsigned short>(tag);
1551 test_mixed<Real, int>(tag);
1552 test_mixed<Real, unsigned int>(tag);
1553 test_mixed<Real, long>(tag);
1554 test_mixed<Real, unsigned long>(tag);
1555 #ifdef BOOST_HAS_LONG_LONG
1556 test_mixed<Real, long long>(tag);
1557 test_mixed<Real, unsigned long long>(tag);
1558 #endif
1559 test_mixed<Real, float>(tag);
1560 test_mixed<Real, double>(tag);
1561 test_mixed<Real, long double>(tag);
1562
1563 typedef typename related_type<Real>::type related_type;
1564 boost::mpl::bool_<boost::multiprecision::is_number<Real>::value && !boost::is_same<related_type, Real>::value> tag2;
1565
1566 test_mixed<Real, related_type>(tag2);
1567
1568 #endif
1569 //
1570 // Integer only functions:
1571 //
1572 test_integer_ops<Real>(typename boost::multiprecision::number_category<Real>::type());
1573 //
1574 // Real number only functions:
1575 //
1576 test_float_ops<Real>(typename boost::multiprecision::number_category<Real>::type());
1577 //
1578 // Test basic arithmetic:
1579 //
1580 Real a(8);
1581 Real b(64);
1582 Real c(500);
1583 Real d(1024);
1584 BOOST_CHECK_EQUAL(a + b , 72);
1585 a += b;
1586 BOOST_CHECK_EQUAL(a , 72);
1587 BOOST_CHECK_EQUAL(a - b , 8);
1588 a -= b;
1589 BOOST_CHECK_EQUAL(a , 8);
1590 BOOST_CHECK_EQUAL(a * b , 8*64L);
1591 a *= b;
1592 BOOST_CHECK_EQUAL(a , 8*64L);
1593 BOOST_CHECK_EQUAL(a / b , 8);
1594 a /= b;
1595 BOOST_CHECK_EQUAL(a , 8);
1596 Real ac(a);
1597 BOOST_CHECK_EQUAL(ac , a);
1598 ac = a * c;
1599 BOOST_CHECK_EQUAL(ac , 8*500L);
1600 ac = 8*500L;
1601 ac = ac + b + c;
1602 BOOST_CHECK_EQUAL(ac , 8*500L+64+500);
1603 ac = a;
1604 ac = b + c + ac;
1605 BOOST_CHECK_EQUAL(ac , 8+64+500);
1606 ac = ac - b + c;
1607 BOOST_CHECK_EQUAL(ac , 8+64+500-64+500);
1608 ac = a;
1609 ac = b + c - ac;
1610 BOOST_CHECK_EQUAL(ac , -8+64+500);
1611 ac = a;
1612 ac = ac * b;
1613 BOOST_CHECK_EQUAL(ac , 8*64);
1614 ac = a;
1615 ac *= b * ac;
1616 BOOST_CHECK_EQUAL(ac , 8*8*64);
1617 ac = b;
1618 ac = ac / a;
1619 BOOST_CHECK_EQUAL(ac , 64/8);
1620 ac = b;
1621 ac /= ac / a;
1622 BOOST_CHECK_EQUAL(ac , 64 / (64/8));
1623 ac = a;
1624 ac = b + ac * a;
1625 BOOST_CHECK_EQUAL(ac , 64 * 2);
1626 ac = a;
1627 ac = b - ac * a;
1628 BOOST_CHECK_EQUAL(ac , 0);
1629 ac = a;
1630 ac = b * (ac + a);
1631 BOOST_CHECK_EQUAL(ac , 64 * (16));
1632 ac = a;
1633 ac = b / (ac * 1);
1634 BOOST_CHECK_EQUAL(ac , 64 / 8);
1635 ac = a;
1636 ac = ac + b;
1637 BOOST_CHECK_EQUAL(ac , 8 + 64);
1638 ac = a;
1639 ac = a + ac;
1640 BOOST_CHECK_EQUAL(ac , 16);
1641 ac = a;
1642 ac = a - ac;
1643 BOOST_CHECK_EQUAL(ac , 0);
1644 ac = a;
1645 ac += a + b;
1646 BOOST_CHECK_EQUAL(ac , 80);
1647 ac = a;
1648 ac += b + a;
1649 BOOST_CHECK_EQUAL(ac , 80);
1650 ac = +a;
1651 BOOST_CHECK_EQUAL(ac , 8);
1652 ac = 8;
1653 ac = a * ac;
1654 BOOST_CHECK_EQUAL(ac , 8*8);
1655 ac = a;
1656 ac = a;
1657 ac += +a;
1658 BOOST_CHECK_EQUAL(ac , 16);
1659 ac = a;
1660 ac += b - a;
1661 BOOST_CHECK_EQUAL(ac , 8 + 64-8);
1662 ac = a;
1663 ac += b*c;
1664 BOOST_CHECK_EQUAL(ac , 8 + 64 * 500);
1665 ac = a;
1666 ac = a;
1667 ac -= +a;
1668 BOOST_CHECK_EQUAL(ac , 0);
1669 ac = a;
1670 if(std::numeric_limits<Real>::is_signed || is_twos_complement_integer<Real>::value)
1671 {
1672 ac = a;
1673 ac -= c - b;
1674 BOOST_CHECK_EQUAL(ac , 8 - (500-64));
1675 ac = a;
1676 ac -= b*c;
1677 BOOST_CHECK_EQUAL(ac , 8 - 500*64);
1678 }
1679 ac = a;
1680 ac += ac * b;
1681 BOOST_CHECK_EQUAL(ac , 8 + 8 * 64);
1682 if(std::numeric_limits<Real>::is_signed || is_twos_complement_integer<Real>::value)
1683 {
1684 ac = a;
1685 ac -= ac * b;
1686 BOOST_CHECK_EQUAL(ac , 8 - 8 * 64);
1687 }
1688 ac = a * 8;
1689 ac *= +a;
1690 BOOST_CHECK_EQUAL(ac , 64 * 8);
1691 ac = a;
1692 ac *= b * c;
1693 BOOST_CHECK_EQUAL(ac , 8 * 64 * 500);
1694 ac = a;
1695 ac *= b / a;
1696 BOOST_CHECK_EQUAL(ac , 8 * 64 / 8);
1697 ac = a;
1698 ac *= b + c;
1699 BOOST_CHECK_EQUAL(ac , 8 * (64 + 500));
1700 ac = b;
1701 ac /= +a;
1702 BOOST_CHECK_EQUAL(ac , 8);
1703 ac = b;
1704 ac /= b / a;
1705 BOOST_CHECK_EQUAL(ac , 64 / (64/8));
1706 ac = b;
1707 ac /= a + Real(0);
1708 BOOST_CHECK_EQUAL(ac , 8);
1709 //
1710 // simple tests with immediate values, these calls can be optimised in many backends:
1711 //
1712 ac = a + b;
1713 BOOST_CHECK_EQUAL(ac , 72);
1714 ac = a + +b;
1715 BOOST_CHECK_EQUAL(ac , 72);
1716 ac = +a + b;
1717 BOOST_CHECK_EQUAL(ac , 72);
1718 ac = +a + +b;
1719 BOOST_CHECK_EQUAL(ac , 72);
1720 ac = a;
1721 ac = b / ac;
1722 BOOST_CHECK_EQUAL(ac , b / a);
1723 //
1724 // Comparisons:
1725 //
1726 BOOST_CHECK_EQUAL((a == b) , false);
1727 BOOST_CHECK_EQUAL((a != b) , true);
1728 BOOST_CHECK_EQUAL((a <= b) , true);
1729 BOOST_CHECK_EQUAL((a < b) , true);
1730 BOOST_CHECK_EQUAL((a >= b) , false);
1731 BOOST_CHECK_EQUAL((a > b) , false);
1732
1733 BOOST_CHECK_EQUAL((a+b == b) , false);
1734 BOOST_CHECK_EQUAL((a+b != b) , true);
1735 BOOST_CHECK_EQUAL((a+b >= b) , true);
1736 BOOST_CHECK_EQUAL((a+b > b) , true);
1737 BOOST_CHECK_EQUAL((a+b <= b) , false);
1738 BOOST_CHECK_EQUAL((a+b < b) , false);
1739
1740 BOOST_CHECK_EQUAL((a == b+a) , false);
1741 BOOST_CHECK_EQUAL((a != b+a) , true);
1742 BOOST_CHECK_EQUAL((a <= b+a) , true);
1743 BOOST_CHECK_EQUAL((a < b+a) , true);
1744 BOOST_CHECK_EQUAL((a >= b+a) , false);
1745 BOOST_CHECK_EQUAL((a > b+a) , false);
1746
1747 BOOST_CHECK_EQUAL((a+b == b+a) , true);
1748 BOOST_CHECK_EQUAL((a+b != b+a) , false);
1749 BOOST_CHECK_EQUAL((a+b <= b+a) , true);
1750 BOOST_CHECK_EQUAL((a+b < b+a) , false);
1751 BOOST_CHECK_EQUAL((a+b >= b+a) , true);
1752 BOOST_CHECK_EQUAL((a+b > b+a) , false);
1753
1754 BOOST_CHECK_EQUAL((8 == b+a) , false);
1755 BOOST_CHECK_EQUAL((8 != b+a) , true);
1756 BOOST_CHECK_EQUAL((8 <= b+a) , true);
1757 BOOST_CHECK_EQUAL((8 < b+a) , true);
1758 BOOST_CHECK_EQUAL((8 >= b+a) , false);
1759 BOOST_CHECK_EQUAL((8 > b+a) , false);
1760 BOOST_CHECK_EQUAL((800 == b+a) , false);
1761 BOOST_CHECK_EQUAL((800 != b+a) , true);
1762 BOOST_CHECK_EQUAL((800 >= b+a) , true);
1763 BOOST_CHECK_EQUAL((800 > b+a) , true);
1764 BOOST_CHECK_EQUAL((800 <= b+a) , false);
1765 BOOST_CHECK_EQUAL((800 < b+a) , false);
1766 BOOST_CHECK_EQUAL((72 == b+a) , true);
1767 BOOST_CHECK_EQUAL((72 != b+a) , false);
1768 BOOST_CHECK_EQUAL((72 <= b+a) , true);
1769 BOOST_CHECK_EQUAL((72 < b+a) , false);
1770 BOOST_CHECK_EQUAL((72 >= b+a) , true);
1771 BOOST_CHECK_EQUAL((72 > b+a) , false);
1772
1773 test_members(a);
1774 //
1775 // Use in Boolean context:
1776 //
1777 a = 0;
1778 if(a)
1779 {
1780 BOOST_ERROR("Unexpected non-zero result");
1781 }
1782 if(!a){}
1783 else
1784 {
1785 BOOST_ERROR("Unexpected zero result");
1786 }
1787 b = 2;
1788 if(!b)
1789 {
1790 BOOST_ERROR("Unexpected zero result");
1791 }
1792 if(b){}
1793 else
1794 {
1795 BOOST_ERROR("Unexpected non-zero result");
1796 }
1797 if(a && b)
1798 {
1799 BOOST_ERROR("Unexpected zero result");
1800 }
1801 if(!(a || b))
1802 {
1803 BOOST_ERROR("Unexpected zero result");
1804 }
1805 if(a + b){}
1806 else
1807 {
1808 BOOST_ERROR("Unexpected zero result");
1809 }
1810 if(b - 2)
1811 {
1812 BOOST_ERROR("Unexpected non-zero result");
1813 }
1814 //
1815 // Test iostreams:
1816 //
1817 std::stringstream ss;
1818 a = 20;
1819 b = 2;
1820 ss << a;
1821 ss >> c;
1822 BOOST_CHECK_EQUAL(a , c);
1823 ss.clear();
1824 ss << a + b;
1825 ss >> c;
1826 BOOST_CHECK_EQUAL(c , 22);
1827 BOOST_CHECK_EQUAL(c , a + b);
1828 //
1829 // More cases for complete code coverage:
1830 //
1831 a = 20;
1832 b = 30;
1833 swap(a, b);
1834 BOOST_CHECK_EQUAL(a , 30);
1835 BOOST_CHECK_EQUAL(b , 20);
1836 a = 20;
1837 b = 30;
1838 std::swap(a, b);
1839 BOOST_CHECK_EQUAL(a , 30);
1840 BOOST_CHECK_EQUAL(b , 20);
1841 a = 20;
1842 b = 30;
1843 a = a + b * 2;
1844 BOOST_CHECK_EQUAL(a , 20 + 30 * 2);
1845 a = 100;
1846 a = a - b * 2;
1847 BOOST_CHECK_EQUAL(a , 100 - 30 * 2);
1848 a = 20;
1849 a = a * (b + 2);
1850 BOOST_CHECK_EQUAL(a , 20 * (32));
1851 a = 20;
1852 a = (b + 2) * a;
1853 BOOST_CHECK_EQUAL(a , 20 * (32));
1854 a = 90;
1855 b = 2;
1856 a = a / (b + 0);
1857 BOOST_CHECK_EQUAL(a , 45);
1858 a = 20;
1859 b = 30;
1860 c = (a * b) + 22;
1861 BOOST_CHECK_EQUAL(c , 20 * 30 + 22);
1862 c = 22 + (a * b);
1863 BOOST_CHECK_EQUAL(c , 20 * 30 + 22);
1864 c = 10;
1865 ac = a + b * c;
1866 BOOST_CHECK_EQUAL(ac , 20 + 30 * 10);
1867 ac = b * c + a;
1868 BOOST_CHECK_EQUAL(ac , 20 + 30 * 10);
1869 a = a + b * c;
1870 BOOST_CHECK_EQUAL(a , 20 + 30 * 10);
1871 a = 20;
1872 b = a + b * c;
1873 BOOST_CHECK_EQUAL(b , 20 + 30 * 10);
1874 b = 30;
1875 c = a + b * c;
1876 BOOST_CHECK_EQUAL(c , 20 + 30 * 10);
1877 c = 10;
1878 c = a + b / c;
1879 BOOST_CHECK_EQUAL(c , 20 + 30 / 10);
1880
1881 //
1882 // Test conditionals:
1883 //
1884 a = 20;
1885 test_conditional(a, +a);
1886 test_conditional(a, (a + 0));
1887
1888 test_signed_ops<Real>(boost::mpl::bool_<std::numeric_limits<Real>::is_signed>());
1889 //
1890 // Test move:
1891 //
1892 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1893 Real m(static_cast<Real&&>(a));
1894 BOOST_CHECK_EQUAL(m, 20);
1895 // Move from already moved from object:
1896 Real m2(static_cast<Real&&>(a));
1897 // assign from moved from object
1898 // (may result in "a" being left in valid state as implementation artifact):
1899 c = static_cast<Real&&>(a);
1900 // assignment to moved-from objects:
1901 c = static_cast<Real&&>(m);
1902 BOOST_CHECK_EQUAL(c, 20);
1903 m2 = c;
1904 BOOST_CHECK_EQUAL(c, 20);
1905 // Destructor of "a" checks destruction of moved-from-object...
1906 Real m3(static_cast<Real&&>(a));
1907 #endif
1908 //
1909 // Bug cases, self assignment first:
1910 //
1911 a = 20;
1912 a = a;
1913 BOOST_CHECK_EQUAL(a, 20);
1914 }
1915
1916