1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
|
// Copyright John Maddock 2013.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifdef _MSC_VER
#define _SCL_SECURE_NO_WARNINGS
#endif
#include <boost/multiprecision/cpp_bin_float.hpp>
#ifdef TEST_MPFR
#include <boost/multiprecision/mpfr.hpp>
#endif
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include "test.hpp"
#include <iostream>
#include <iomanip>
template <class T>
T generate_random()
{
typedef int e_type;
static boost::random::mt19937 gen;
T val = gen();
T prev_val = -1;
while (val != prev_val)
{
val *= (gen.max)();
prev_val = val;
val += gen();
}
e_type e;
val = frexp(val, &e);
static boost::random::uniform_int_distribution<e_type> ui(-20, 20);
return ldexp(val, ui(gen));
}
using namespace boost::multiprecision;
#ifdef TEST_MPFR
typedef number<mpfr_float_backend<35> > good_type;
#else
typedef double good_type;
#endif
typedef number<cpp_bin_float<std::numeric_limits<good_type>::digits, digit_base_2>, et_off> test_type;
void test_special_cases()
{
#if !defined(BOOST_CI_ASAN_BUILD) && !defined(BOOST_CI_USAN_BUID)
test_type max_val = (std::numeric_limits<test_type>::max)();
test_type denorm_min_val = std::numeric_limits<test_type>::denorm_min();
test_type min_val = (std::numeric_limits<test_type>::min)();
test_type eps = std::numeric_limits<test_type>::epsilon();
test_type inf_val = (std::numeric_limits<test_type>::infinity)();
test_type nan_val = (std::numeric_limits<test_type>::quiet_NaN)();
test_type half = 0.5;
test_type one_point_5 = 1.5;
BOOST_CHECK((boost::math::isnormal)(max_val));
BOOST_CHECK((boost::math::isnormal)(-max_val));
BOOST_CHECK((boost::math::isnormal)(min_val));
BOOST_CHECK((boost::math::isnormal)(-min_val));
BOOST_CHECK((boost::math::isnormal)(denorm_min_val));
BOOST_CHECK((boost::math::isnormal)(-denorm_min_val));
BOOST_CHECK((boost::math::isinf)(inf_val));
BOOST_CHECK((boost::math::isinf)(-inf_val));
BOOST_CHECK((boost::math::isnan)(nan_val));
BOOST_CHECK((boost::math::isnan)(-nan_val));
if (!std::numeric_limits<test_type>::has_denorm) {
BOOST_CHECK_EQUAL(denorm_min_val, min_val);
} else {
BOOST_CHECK_LE(denorm_min_val, min_val);
}
// Adding epsilon will increment 1.0:
BOOST_CHECK(test_type(1) + eps != test_type(1));
BOOST_CHECK(test_type(1) + eps / 2 == test_type(1));
// But it's not the smallest value that will do that:
test_type small = 1 + eps;
small = ldexp(small, -std::numeric_limits<test_type>::digits);
BOOST_CHECK(test_type(1) + small != test_type(1));
// And if we increment 1.0 first, then an even smaller
// addition will round up:
test_type one_next = test_type(1) + eps;
BOOST_CHECK(one_next + eps / 2 != one_next);
// Overflow:
BOOST_CHECK_EQUAL(max_val + max_val * eps, inf_val);
BOOST_CHECK_EQUAL(-max_val - max_val * eps, -inf_val);
BOOST_CHECK_EQUAL(max_val * 2, inf_val);
BOOST_CHECK_EQUAL(max_val * -2, -inf_val);
BOOST_CHECK_EQUAL(max_val / half, inf_val);
BOOST_CHECK_EQUAL(max_val / -half, -inf_val);
BOOST_CHECK_EQUAL(max_val / min_val, inf_val);
BOOST_CHECK_EQUAL(max_val / -min_val, -inf_val);
BOOST_CHECK_EQUAL(max_val / denorm_min_val, inf_val);
BOOST_CHECK_EQUAL(max_val / -denorm_min_val, -inf_val);
// Underflow:
BOOST_CHECK_EQUAL(min_val * 2 - one_point_5 * min_val, 0);
BOOST_CHECK_EQUAL(-min_val * 2 + one_point_5 * min_val, 0);
BOOST_CHECK_EQUAL(min_val / 2, 0);
BOOST_CHECK_EQUAL(min_val / max_val, 0);
BOOST_CHECK_EQUAL(min_val * half, 0);
BOOST_CHECK_EQUAL(min_val - min_val, 0);
BOOST_CHECK_EQUAL(-min_val + min_val, 0);
BOOST_CHECK_EQUAL(denorm_min_val * 2 - one_point_5 * denorm_min_val, 0);
BOOST_CHECK_EQUAL(-denorm_min_val * 2 + one_point_5 * denorm_min_val, 0);
BOOST_CHECK_EQUAL(denorm_min_val / 2, 0);
BOOST_CHECK_EQUAL(denorm_min_val / max_val, 0);
BOOST_CHECK_EQUAL(denorm_min_val * half, 0);
BOOST_CHECK_EQUAL(denorm_min_val - denorm_min_val, 0);
BOOST_CHECK_EQUAL(-denorm_min_val + denorm_min_val, 0);
// Things which should not over/underflow:
BOOST_CHECK_EQUAL((min_val * 2) / 2, min_val);
BOOST_CHECK_GE((min_val * 2.0000001) / 1.9999999999999999, min_val);
BOOST_CHECK_EQUAL(min_val * 2 - min_val, min_val);
BOOST_CHECK_EQUAL((denorm_min_val * 2) / 2, denorm_min_val);
BOOST_CHECK_GE((denorm_min_val * 2.0000001) / 1.9999999999999999, denorm_min_val);
BOOST_CHECK_EQUAL(denorm_min_val * 2 - denorm_min_val, denorm_min_val);
BOOST_CHECK_EQUAL(-max_val + max_val, 0);
BOOST_CHECK_EQUAL(max_val - max_val, 0);
BOOST_CHECK_EQUAL((max_val / 2) * 2, max_val);
BOOST_CHECK_LE((max_val / 2.0000001) * 1.9999999999999999, max_val);
BOOST_CHECK_EQUAL(max_val / 2 + max_val / 2, max_val);
// Things involving zero:
BOOST_CHECK_EQUAL(max_val + 0, max_val);
BOOST_CHECK_EQUAL(max_val - 0, max_val);
BOOST_CHECK_EQUAL(0 + max_val, max_val);
BOOST_CHECK_EQUAL(0 - max_val, -max_val);
BOOST_CHECK_EQUAL(max_val * 0, 0);
BOOST_CHECK_EQUAL(0 * max_val, 0);
BOOST_CHECK_EQUAL(max_val / 0, inf_val);
BOOST_CHECK_EQUAL(0 / max_val, 0);
BOOST_CHECK_EQUAL(-max_val / 0, -inf_val);
BOOST_CHECK_EQUAL(0 / -max_val, 0);
// Things involving infinity:
BOOST_CHECK_EQUAL(inf_val + 2, inf_val);
BOOST_CHECK_EQUAL(inf_val - 2, inf_val);
BOOST_CHECK_EQUAL(inf_val + -2, inf_val);
BOOST_CHECK_EQUAL(inf_val - -2, inf_val);
BOOST_CHECK_EQUAL(-inf_val + 2, -inf_val);
BOOST_CHECK_EQUAL(-inf_val - 2, -inf_val);
BOOST_CHECK_EQUAL(-inf_val + -2, -inf_val);
BOOST_CHECK_EQUAL(-inf_val - -2, -inf_val);
BOOST_CHECK_EQUAL(2 + inf_val, inf_val);
BOOST_CHECK_EQUAL(2 - inf_val, -inf_val);
BOOST_CHECK_EQUAL(-2 + inf_val, inf_val);
BOOST_CHECK_EQUAL(-2 - inf_val, -inf_val);
BOOST_CHECK_EQUAL(2 + (-inf_val), -inf_val);
BOOST_CHECK_EQUAL(2 - (-inf_val), inf_val);
BOOST_CHECK_EQUAL(-2 + (-inf_val), -inf_val);
BOOST_CHECK_EQUAL(-2 - (-inf_val), inf_val);
BOOST_CHECK_EQUAL(sqrt(inf_val), inf_val);
BOOST_CHECK(boost::math::isnan(sqrt(-inf_val)));
BOOST_CHECK_EQUAL(inf_val + test_type(2), inf_val);
BOOST_CHECK_EQUAL(inf_val - test_type(2), inf_val);
BOOST_CHECK_EQUAL(inf_val + test_type(-2), inf_val);
BOOST_CHECK_EQUAL(inf_val - test_type(-2), inf_val);
BOOST_CHECK_EQUAL(-inf_val + test_type(2), -inf_val);
BOOST_CHECK_EQUAL(-inf_val - test_type(2), -inf_val);
BOOST_CHECK_EQUAL(-inf_val + test_type(-2), -inf_val);
BOOST_CHECK_EQUAL(-inf_val - test_type(-2), -inf_val);
BOOST_CHECK_EQUAL(test_type(2) + inf_val, inf_val);
BOOST_CHECK_EQUAL(test_type(2) - inf_val, -inf_val);
BOOST_CHECK_EQUAL(test_type(-2) + inf_val, inf_val);
BOOST_CHECK_EQUAL(test_type(-2) - inf_val, -inf_val);
BOOST_CHECK_EQUAL(test_type(2) + (-inf_val), -inf_val);
BOOST_CHECK_EQUAL(test_type(2) - (-inf_val), inf_val);
BOOST_CHECK_EQUAL(test_type(-2) + (-inf_val), -inf_val);
BOOST_CHECK_EQUAL(test_type(-2) - (-inf_val), inf_val);
BOOST_CHECK((boost::math::isnan)(inf_val - inf_val));
BOOST_CHECK_EQUAL(inf_val * 2, inf_val);
BOOST_CHECK_EQUAL(-inf_val * 2, -inf_val);
BOOST_CHECK_EQUAL(inf_val * -2, -inf_val);
BOOST_CHECK_EQUAL(-inf_val * -2, inf_val);
BOOST_CHECK_EQUAL(inf_val * test_type(-2), -inf_val);
BOOST_CHECK_EQUAL(-inf_val * test_type(-2), inf_val);
BOOST_CHECK((boost::math::isnan)(inf_val * 0));
BOOST_CHECK((boost::math::isnan)(-inf_val * 0));
BOOST_CHECK_EQUAL(inf_val / 2, inf_val);
BOOST_CHECK_EQUAL(-inf_val / 2, -inf_val);
BOOST_CHECK_EQUAL(inf_val / -2, -inf_val);
BOOST_CHECK_EQUAL(-inf_val / -2, inf_val);
BOOST_CHECK_EQUAL(inf_val / test_type(-2), -inf_val);
BOOST_CHECK_EQUAL(-inf_val / test_type(-2), inf_val);
BOOST_CHECK_EQUAL(inf_val / 0, inf_val);
BOOST_CHECK_EQUAL(-inf_val / 0, -inf_val);
BOOST_CHECK((boost::math::isnan)(inf_val / inf_val));
BOOST_CHECK((boost::math::isnan)(-inf_val / inf_val));
// Things involving nan:
BOOST_CHECK((boost::math::isnan)(nan_val + 2));
BOOST_CHECK((boost::math::isnan)(nan_val - 2));
BOOST_CHECK((boost::math::isnan)(nan_val + 0));
BOOST_CHECK((boost::math::isnan)(nan_val - 0));
BOOST_CHECK((boost::math::isnan)(nan_val + inf_val));
BOOST_CHECK((boost::math::isnan)(nan_val - inf_val));
BOOST_CHECK((boost::math::isnan)(nan_val + nan_val));
BOOST_CHECK((boost::math::isnan)(nan_val - nan_val));
BOOST_CHECK((boost::math::isnan)(2 + nan_val));
BOOST_CHECK((boost::math::isnan)(2 - nan_val));
BOOST_CHECK((boost::math::isnan)(0 - nan_val));
BOOST_CHECK((boost::math::isnan)(0 - nan_val));
BOOST_CHECK((boost::math::isnan)(inf_val + nan_val));
BOOST_CHECK((boost::math::isnan)(inf_val - nan_val));
BOOST_CHECK((boost::math::isnan)(nan_val * 2));
BOOST_CHECK((boost::math::isnan)(nan_val / 2));
BOOST_CHECK((boost::math::isnan)(nan_val * 0));
BOOST_CHECK((boost::math::isnan)(nan_val / 0));
BOOST_CHECK((boost::math::isnan)(nan_val * inf_val));
BOOST_CHECK((boost::math::isnan)(nan_val / inf_val));
BOOST_CHECK((boost::math::isnan)(nan_val * nan_val));
BOOST_CHECK((boost::math::isnan)(nan_val / nan_val));
BOOST_CHECK((boost::math::isnan)(2 * nan_val));
BOOST_CHECK((boost::math::isnan)(2 / nan_val));
BOOST_CHECK((boost::math::isnan)(0 / nan_val));
BOOST_CHECK((boost::math::isnan)(0 / nan_val));
BOOST_CHECK((boost::math::isnan)(inf_val * nan_val));
BOOST_CHECK((boost::math::isnan)(inf_val / nan_val));
// Corner cases:
BOOST_CHECK_EQUAL((max_val * half) / half, max_val);
BOOST_CHECK_EQUAL((max_val / 2) * 2, max_val);
BOOST_CHECK_EQUAL((min_val / half) * half, min_val);
BOOST_CHECK_EQUAL((min_val * 2) / 2, min_val);
BOOST_CHECK_EQUAL(max_val + min_val, max_val);
BOOST_CHECK_EQUAL(min_val + max_val, max_val);
BOOST_CHECK_EQUAL(max_val - min_val, max_val);
BOOST_CHECK_EQUAL(min_val - max_val, -max_val);
BOOST_CHECK_EQUAL((denorm_min_val / half) * half, denorm_min_val);
BOOST_CHECK_EQUAL((denorm_min_val * 2) / 2, denorm_min_val);
BOOST_CHECK_EQUAL(max_val + denorm_min_val, max_val);
BOOST_CHECK_EQUAL(denorm_min_val + max_val, max_val);
BOOST_CHECK_EQUAL(max_val - denorm_min_val, max_val);
BOOST_CHECK_EQUAL(denorm_min_val - max_val, -max_val);
// Signed zeros:
BOOST_CHECK(boost::math::signbit(min_val * -min_val));
BOOST_CHECK(boost::math::signbit(min_val * min_val) == 0);
BOOST_CHECK(boost::math::signbit(-min_val * -min_val) == 0);
BOOST_CHECK(boost::math::signbit(-min_val * min_val));
BOOST_CHECK(boost::math::signbit(min_val / max_val) == 0);
BOOST_CHECK(boost::math::signbit(min_val / -max_val));
BOOST_CHECK(boost::math::signbit(-min_val / -max_val) == 0);
BOOST_CHECK(boost::math::signbit(-min_val / max_val));
BOOST_CHECK(boost::math::signbit(min_val / 2) == 0);
BOOST_CHECK(boost::math::signbit(min_val / -2));
BOOST_CHECK(boost::math::signbit(-min_val / -2) == 0);
BOOST_CHECK(boost::math::signbit(-min_val / 2));
test_type neg_zero = min_val * -min_val;
BOOST_CHECK(boost::math::signbit(denorm_min_val * -denorm_min_val));
BOOST_CHECK(boost::math::signbit(denorm_min_val * denorm_min_val) == 0);
BOOST_CHECK(boost::math::signbit(-denorm_min_val * -denorm_min_val) == 0);
BOOST_CHECK(boost::math::signbit(-denorm_min_val * denorm_min_val));
BOOST_CHECK(boost::math::signbit(denorm_min_val / max_val) == 0);
BOOST_CHECK(boost::math::signbit(denorm_min_val / -max_val));
BOOST_CHECK(boost::math::signbit(-denorm_min_val / -max_val) == 0);
BOOST_CHECK(boost::math::signbit(-denorm_min_val / max_val));
BOOST_CHECK(boost::math::signbit(denorm_min_val / 2) == 0);
BOOST_CHECK(boost::math::signbit(denorm_min_val / -2));
BOOST_CHECK(boost::math::signbit(-denorm_min_val / -2) == 0);
BOOST_CHECK(boost::math::signbit(-denorm_min_val / 2));
test_type neg_denorm_zero = denorm_min_val * -denorm_min_val;
BOOST_CHECK_EQUAL(neg_zero, neg_denorm_zero);
test_type zero = 0;
// Arithmetic involving signed zero:
BOOST_CHECK_EQUAL(-neg_zero, 0);
BOOST_CHECK(!boost::math::signbit(-neg_zero));
BOOST_CHECK_EQUAL(neg_zero + 2, 2);
BOOST_CHECK_EQUAL(neg_zero + test_type(2), 2);
BOOST_CHECK_EQUAL(2 + neg_zero, 2);
BOOST_CHECK_EQUAL(test_type(2) + neg_zero, 2);
BOOST_CHECK_EQUAL(neg_zero + -2, -2);
BOOST_CHECK_EQUAL(neg_zero + test_type(-2), -2);
BOOST_CHECK_EQUAL(-2 + neg_zero, -2);
BOOST_CHECK_EQUAL(test_type(-2) + neg_zero, -2);
BOOST_CHECK_EQUAL(neg_zero - 2, -2);
BOOST_CHECK_EQUAL(neg_zero - test_type(2), -2);
BOOST_CHECK_EQUAL(2 - neg_zero, 2);
BOOST_CHECK_EQUAL(test_type(2) - neg_zero, 2);
BOOST_CHECK_EQUAL(neg_zero - -2, 2);
BOOST_CHECK_EQUAL(neg_zero - test_type(-2), 2);
BOOST_CHECK_EQUAL(-2 - neg_zero, -2);
BOOST_CHECK_EQUAL(test_type(-2) - neg_zero, -2);
BOOST_CHECK(!boost::math::signbit(test_type(2) + test_type(-2)));
BOOST_CHECK(!boost::math::signbit(test_type(2) - test_type(2)));
BOOST_CHECK(!boost::math::signbit(test_type(-2) - test_type(-2)));
BOOST_CHECK(!boost::math::signbit(test_type(-2) + test_type(2)));
BOOST_CHECK(!boost::math::signbit(zero + zero));
BOOST_CHECK(!boost::math::signbit(zero - zero));
BOOST_CHECK(!boost::math::signbit(neg_zero + zero));
BOOST_CHECK(!boost::math::signbit(zero + neg_zero));
BOOST_CHECK(boost::math::signbit(neg_zero + neg_zero));
BOOST_CHECK(boost::math::signbit(neg_zero - zero));
BOOST_CHECK(!boost::math::signbit(zero - neg_zero));
BOOST_CHECK(!boost::math::signbit(neg_zero - neg_zero));
small = 0.25;
BOOST_CHECK(!boost::math::signbit(floor(small)));
BOOST_CHECK(!boost::math::signbit(round(small)));
BOOST_CHECK(!boost::math::signbit(trunc(small)));
small = -small;
BOOST_CHECK(boost::math::signbit(ceil(small)));
BOOST_CHECK(boost::math::signbit(round(small)));
BOOST_CHECK(boost::math::signbit(trunc(small)));
BOOST_CHECK_EQUAL(neg_zero * 2, 0);
BOOST_CHECK_EQUAL(neg_zero * test_type(2), 0);
BOOST_CHECK_EQUAL(2 * neg_zero, 0);
BOOST_CHECK_EQUAL(test_type(2) * neg_zero, 0);
BOOST_CHECK_EQUAL(neg_zero * -2, 0);
BOOST_CHECK_EQUAL(neg_zero * test_type(-2), 0);
BOOST_CHECK_EQUAL(-2 * neg_zero, 0);
BOOST_CHECK_EQUAL(test_type(-2) * neg_zero, 0);
BOOST_CHECK(boost::math::signbit(neg_zero * 2));
BOOST_CHECK(boost::math::signbit(neg_zero * test_type(2)));
BOOST_CHECK(boost::math::signbit(2 * neg_zero));
BOOST_CHECK(boost::math::signbit(test_type(2) * neg_zero));
BOOST_CHECK(!boost::math::signbit(neg_zero * -2));
BOOST_CHECK(!boost::math::signbit(neg_zero * test_type(-2)));
BOOST_CHECK(!boost::math::signbit(-2 * neg_zero));
BOOST_CHECK(!boost::math::signbit(test_type(-2) * neg_zero));
BOOST_CHECK_EQUAL(neg_zero / 2, 0);
BOOST_CHECK_EQUAL(neg_zero / test_type(2), 0);
BOOST_CHECK_EQUAL(2 / neg_zero, -inf_val);
BOOST_CHECK_EQUAL(test_type(2) / neg_zero, -inf_val);
BOOST_CHECK_EQUAL(neg_zero / -2, 0);
BOOST_CHECK_EQUAL(neg_zero / test_type(-2), 0);
BOOST_CHECK_EQUAL(-2 / neg_zero, inf_val);
BOOST_CHECK_EQUAL(test_type(-2) / neg_zero, inf_val);
BOOST_CHECK(boost::math::signbit(neg_zero / 2));
BOOST_CHECK(boost::math::signbit(neg_zero / test_type(2)));
BOOST_CHECK(boost::math::signbit(2 / neg_zero));
BOOST_CHECK(boost::math::signbit(test_type(2) / neg_zero));
BOOST_CHECK(!boost::math::signbit(neg_zero / -2));
BOOST_CHECK(!boost::math::signbit(neg_zero / test_type(-2)));
BOOST_CHECK(!boost::math::signbit(-2 / neg_zero));
BOOST_CHECK(!boost::math::signbit(test_type(-2) / neg_zero));
BOOST_CHECK(boost::math::signbit(neg_zero.convert_to<double>()));
BOOST_CHECK(boost::math::signbit(neg_zero.convert_to<float>()));
BOOST_CHECK(boost::math::signbit(neg_zero.convert_to<long double>()));
BOOST_CHECK(!boost::math::signbit(zero.convert_to<double>()));
BOOST_CHECK(!boost::math::signbit(zero.convert_to<float>()));
BOOST_CHECK(!boost::math::signbit(zero.convert_to<long double>()));
// Conversions to other types of special values:
if (std::numeric_limits<float>::has_infinity)
{
BOOST_CHECK_EQUAL(inf_val.convert_to<float>(), std::numeric_limits<float>::infinity());
BOOST_CHECK_EQUAL((-inf_val).convert_to<float>(), -std::numeric_limits<float>::infinity());
}
if (std::numeric_limits<float>::has_quiet_NaN)
{
BOOST_CHECK((boost::math::isnan)(nan_val.convert_to<float>()));
}
if (std::numeric_limits<double>::has_infinity)
{
BOOST_CHECK_EQUAL(inf_val.convert_to<double>(), std::numeric_limits<double>::infinity());
BOOST_CHECK_EQUAL((-inf_val).convert_to<double>(), -std::numeric_limits<double>::infinity());
}
if (std::numeric_limits<double>::has_quiet_NaN)
{
BOOST_CHECK((boost::math::isnan)(nan_val.convert_to<double>()));
}
if (std::numeric_limits<long double>::has_infinity)
{
BOOST_CHECK_EQUAL(inf_val.convert_to<long double>(), std::numeric_limits<long double>::infinity());
BOOST_CHECK_EQUAL((-inf_val).convert_to<long double>(), -std::numeric_limits<long double>::infinity());
}
if (std::numeric_limits<long double>::has_quiet_NaN)
{
BOOST_CHECK((boost::math::isnan)(nan_val.convert_to<long double>()));
}
//
// Bug https://svn.boost.org/trac/boost/attachment/ticket/12580
//
using std::ldexp;
test_type a(1);
test_type b = ldexp(test_type(0.99), -std::numeric_limits<test_type>::digits);
good_type ga(1);
good_type gb = ldexp(good_type(0.99), -std::numeric_limits<good_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(test_type(0.5), -std::numeric_limits<test_type>::digits);
gb = ldexp(good_type(0.5), -std::numeric_limits<good_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(test_type(1), -std::numeric_limits<test_type>::digits);
gb = ldexp(good_type(1), -std::numeric_limits<good_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(test_type(0.50000000001), -std::numeric_limits<test_type>::digits);
gb = ldexp(good_type(0.50000000001), -std::numeric_limits<good_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
a = a + ldexp(a, -20);
ga = ga + ldexp(ga, -20);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(test_type(0.5), -std::numeric_limits<test_type>::digits);
gb = ldexp(good_type(0.5), -std::numeric_limits<good_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(test_type(1), -std::numeric_limits<test_type>::digits);
gb = ldexp(good_type(1), -std::numeric_limits<good_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(test_type(0.50000000001), -std::numeric_limits<test_type>::digits);
gb = ldexp(good_type(0.50000000001), -std::numeric_limits<good_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
a = 1;
a = boost::math::float_prior(a);
ga = 1;
ga = boost::math::float_prior(ga);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(test_type(0.5), -std::numeric_limits<test_type>::digits);
gb = ldexp(good_type(0.5), -std::numeric_limits<good_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(test_type(1), -std::numeric_limits<test_type>::digits);
gb = ldexp(good_type(1), -std::numeric_limits<good_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(test_type(0.50000000001), -std::numeric_limits<test_type>::digits);
gb = ldexp(good_type(0.50000000001), -std::numeric_limits<good_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
a = boost::math::float_next(test_type(1));
ga = boost::math::float_next(good_type(1));
b = ldexp(boost::math::float_prior(test_type(1)), -std::numeric_limits<test_type>::digits);
gb = ldexp(boost::math::float_prior(good_type(1)), -std::numeric_limits<test_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(b, -1);
gb = ldexp(gb, -1);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
a = 1.75; // even mantissa, not a power of 2
ga = 1.75;
b = ldexp(test_type(1), -std::numeric_limits<test_type>::digits);
gb = ldexp(good_type(1), -std::numeric_limits<test_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(b, -1);
gb = ldexp(gb, -1);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(boost::math::float_prior(test_type(1)), -std::numeric_limits<test_type>::digits);
gb = ldexp(boost::math::float_prior(good_type(1)), -std::numeric_limits<test_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(b, -1);
gb = ldexp(gb, -1);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(test_type(0.75), -std::numeric_limits<test_type>::digits); // even mantissa not a power of 2.
gb = ldexp(good_type(0.75), -std::numeric_limits<test_type>::digits);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
b = ldexp(b, -1);
gb = ldexp(gb, -1);
BOOST_CHECK_EQUAL(good_type(test_type(a - b)), good_type(ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - a)), good_type(gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + b)), good_type(ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + a)), good_type(gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(a - -b)), good_type(ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b - -a)), good_type(gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(a + -b)), good_type(ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(b + -a)), good_type(gb + -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - b)), good_type(-ga - gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - a)), good_type(-gb - ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + b)), good_type(-ga + gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + a)), good_type(-gb + ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a - -b)), good_type(-ga - -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b - -a)), good_type(-gb - -ga));
BOOST_CHECK_EQUAL(good_type(test_type(-a + -b)), good_type(-ga + -gb));
BOOST_CHECK_EQUAL(good_type(test_type(-b + -a)), good_type(-gb + -ga));
#endif
}
int main()
{
// compile times are too long for CI when ASAN is enabled, prune things down a bit:
#if !defined(BOOST_CI_ASAN_BUILD) && !defined(BOOST_CI_USAN_BUID)
test_special_cases();
#endif
unsigned error_count = 0;
for (unsigned i = 0; i < 100000; ++i)
{
good_type a = generate_random<good_type>();
good_type b = generate_random<good_type>();
test_type ta(a);
test_type tb(b);
BOOST_CHECK_EQUAL(test_type(a * b), ta * tb);
BOOST_CHECK_EQUAL(test_type(-a * b), -ta * tb);
BOOST_CHECK_EQUAL(test_type(a * -b), ta * -tb);
BOOST_CHECK_EQUAL(test_type(-a * -b), -ta * -tb);
BOOST_CHECK_EQUAL(test_type(a + b), ta + tb);
BOOST_CHECK_EQUAL(test_type(-a + b), -ta + tb);
BOOST_CHECK_EQUAL(test_type(a + -b), ta + -tb);
BOOST_CHECK_EQUAL(test_type(-a + -b), -ta + -tb);
BOOST_CHECK_EQUAL(test_type(a - b), ta - tb);
BOOST_CHECK_EQUAL(test_type(-a - b), -ta - tb);
BOOST_CHECK_EQUAL(test_type(a - -b), ta - -tb);
BOOST_CHECK_EQUAL(test_type(-a - -b), -ta - -tb);
BOOST_CHECK_EQUAL(test_type(a / b), ta / tb);
BOOST_CHECK_EQUAL(test_type(-a / b), -ta / tb);
BOOST_CHECK_EQUAL(test_type(a / -b), ta / -tb);
BOOST_CHECK_EQUAL(test_type(-a / -b), -ta / -tb);
BOOST_CHECK_EQUAL(test_type(sqrt(a)), sqrt(ta));
BOOST_CHECK_EQUAL(test_type(floor(a)), floor(ta));
BOOST_CHECK_EQUAL(test_type(floor(-a)), floor(-ta));
BOOST_CHECK_EQUAL(test_type(ceil(a)), ceil(ta));
BOOST_CHECK_EQUAL(test_type(ceil(-a)), ceil(-ta));
#ifdef TEST_MPFR
//
// Conversions:
//
BOOST_CHECK_EQUAL(a.convert_to<double>(), ta.convert_to<double>());
BOOST_CHECK_EQUAL(a.convert_to<float>(), ta.convert_to<float>());
BOOST_CHECK_EQUAL(b.convert_to<double>(), tb.convert_to<double>());
BOOST_CHECK_EQUAL(b.convert_to<float>(), tb.convert_to<float>());
#else
BOOST_CHECK_EQUAL(a, ta.convert_to<double>());
BOOST_CHECK_EQUAL(static_cast<float>(a), ta.convert_to<float>());
BOOST_CHECK_EQUAL(b, tb.convert_to<double>());
BOOST_CHECK_EQUAL(static_cast<float>(b), tb.convert_to<float>());
#endif
static boost::random::mt19937 i_gen;
int si = i_gen();
BOOST_CHECK_EQUAL(test_type(a * si), ta * si);
BOOST_CHECK_EQUAL(test_type(-a * si), -ta * si);
BOOST_CHECK_EQUAL(test_type(-a * -si), -ta * -si);
BOOST_CHECK_EQUAL(test_type(a * -si), ta * -si);
unsigned ui = std::abs(si);
BOOST_CHECK_EQUAL(test_type(a * ui), ta * ui);
BOOST_CHECK_EQUAL(test_type(-a * ui), -ta * ui);
// Divide:
BOOST_CHECK_EQUAL(test_type(a / si), ta / si);
BOOST_CHECK_EQUAL(test_type(-a / si), -ta / si);
BOOST_CHECK_EQUAL(test_type(-a / -si), -ta / -si);
BOOST_CHECK_EQUAL(test_type(a / -si), ta / -si);
BOOST_CHECK_EQUAL(test_type(a / ui), ta / ui);
BOOST_CHECK_EQUAL(test_type(-a / ui), -ta / ui);
// Error reporting:
if ((unsigned)boost::detail::test_errors() != error_count)
{
error_count = boost::detail::test_errors();
std::cout << std::setprecision(std::numeric_limits<test_type>::max_digits10) << std::scientific;
std::cout << "a (mpfr) = " << a << std::endl;
std::cout << "a (test) = " << ta << std::endl;
std::cout << "b (mpfr) = " << b << std::endl;
std::cout << "b (test) = " << tb << std::endl;
std::cout << "si = " << si << std::endl;
std::cout << "ui = " << ui << std::endl;
}
}
return boost::report_errors();
}
|