]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | /////////////////////////////////////////////////////////////// |
2 | // Copyright 2017 John Maddock. Distributed under the Boost | |
3 | // Software License, Version 1.0. (See accompanying file | |
92f5a8d4 | 4 | // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt |
b32b8144 FG |
5 | |
6 | // | |
7 | // Check results of truncated overflow. | |
8 | // | |
9 | ||
10 | #ifdef _MSC_VER | |
92f5a8d4 | 11 | #define _SCL_SECURE_NO_WARNINGS |
b32b8144 FG |
12 | #endif |
13 | ||
14 | #include <boost/multiprecision/cpp_int.hpp> | |
15 | #include "test.hpp" | |
16 | #include <boost/random/mersenne_twister.hpp> | |
17 | #include <boost/random/uniform_int.hpp> | |
18 | ||
19 | template <class T> | |
20 | T generate_random(unsigned bits_wanted) | |
21 | { | |
92f5a8d4 | 22 | static boost::random::mt19937 gen; |
b32b8144 FG |
23 | typedef boost::random::mt19937::result_type random_type; |
24 | ||
92f5a8d4 | 25 | T max_val; |
b32b8144 | 26 | unsigned digits; |
92f5a8d4 | 27 | if (std::numeric_limits<T>::is_bounded && (bits_wanted == (unsigned)std::numeric_limits<T>::digits)) |
b32b8144 FG |
28 | { |
29 | max_val = (std::numeric_limits<T>::max)(); | |
92f5a8d4 | 30 | digits = std::numeric_limits<T>::digits; |
b32b8144 FG |
31 | } |
32 | else | |
33 | { | |
34 | max_val = T(1) << bits_wanted; | |
92f5a8d4 | 35 | digits = bits_wanted; |
b32b8144 FG |
36 | } |
37 | ||
38 | unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1; | |
92f5a8d4 TL |
39 | while ((random_type(1) << bits_per_r_val) > (gen.max)()) |
40 | --bits_per_r_val; | |
b32b8144 FG |
41 | |
42 | unsigned terms_needed = digits / bits_per_r_val + 1; | |
43 | ||
44 | T val = 0; | |
92f5a8d4 | 45 | for (unsigned i = 0; i < terms_needed; ++i) |
b32b8144 FG |
46 | { |
47 | val *= (gen.max)(); | |
48 | val += gen(); | |
49 | } | |
50 | val %= max_val; | |
51 | return val; | |
52 | } | |
53 | ||
b32b8144 FG |
54 | template <class Number> |
55 | void test() | |
56 | { | |
57 | using namespace boost::multiprecision; | |
58 | typedef Number test_type; | |
59 | ||
92f5a8d4 | 60 | for (unsigned i = 30; i < std::numeric_limits<test_type>::digits; ++i) |
b32b8144 | 61 | { |
92f5a8d4 | 62 | for (unsigned j = std::numeric_limits<test_type>::digits - i - 1; j < std::numeric_limits<test_type>::digits; ++j) |
b32b8144 | 63 | { |
92f5a8d4 | 64 | for (unsigned k = 0; k < 10; ++k) |
b32b8144 FG |
65 | { |
66 | test_type a = static_cast<test_type>(generate_random<cpp_int>(i)); | |
67 | test_type b = static_cast<test_type>(generate_random<cpp_int>(j)); | |
68 | test_type c = static_cast<test_type>(cpp_int(a) * cpp_int(b)); | |
69 | test_type d = a * b; | |
70 | BOOST_CHECK_EQUAL(c, d); | |
71 | ||
92f5a8d4 | 72 | if ((k == 0) && (j == 0)) |
b32b8144 | 73 | { |
92f5a8d4 | 74 | for (unsigned s = 1; s < std::numeric_limits<test_type>::digits; ++s) |
b32b8144 FG |
75 | BOOST_CHECK_EQUAL(a << s, test_type(cpp_int(a) << s)); |
76 | } | |
77 | } | |
78 | } | |
79 | } | |
80 | } | |
81 | ||
82 | int main() | |
83 | { | |
84 | using namespace boost::multiprecision; | |
85 | ||
86 | test<int512_t>(); | |
87 | test<uint512_t>(); | |
88 | ||
89 | // | |
90 | // We also need to test type with "odd" bit counts in order to ensure full code coverage: | |
91 | // | |
92 | test<number<cpp_int_backend<528, 528, signed_magnitude, unchecked, void> > >(); | |
93 | test<number<cpp_int_backend<528, 528, unsigned_magnitude, unchecked, void> > >(); | |
94 | test<number<cpp_int_backend<48, 48, signed_magnitude, unchecked, void> > >(); | |
95 | test<number<cpp_int_backend<48, 48, unsigned_magnitude, unchecked, void> > >(); | |
96 | return boost::report_errors(); | |
97 | } |