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 https://www.boost.org/LICENSE_1_0.txt
7 // Compare arithmetic results using fixed_int to GMP results.
11 #define _SCL_SECURE_NO_WARNINGS
15 // This ensures all our code gets tested, even though it may
16 // not be the fastest configuration in normal use:
18 #define BOOST_MP_USE_LIMB_SHIFT
20 #include <boost/multiprecision/gmp.hpp>
21 #include <boost/multiprecision/cpp_int.hpp>
22 #include <boost/random/mersenne_twister.hpp>
23 #include <boost/random/uniform_int.hpp>
24 #include <boost/timer.hpp>
28 #pragma warning(disable : 4127) // Conditional expression is constant
36 T
generate_random(unsigned bits_wanted
)
38 static boost::random::mt19937 gen
;
39 typedef boost::random::mt19937::result_type random_type
;
43 if (std::numeric_limits
<T
>::is_bounded
&& (bits_wanted
== (unsigned)std::numeric_limits
<T
>::digits
))
45 max_val
= (std::numeric_limits
<T
>::max
)();
46 digits
= std::numeric_limits
<T
>::digits
;
50 max_val
= T(1) << bits_wanted
;
54 unsigned bits_per_r_val
= std::numeric_limits
<random_type
>::digits
- 1;
55 while ((random_type(1) << bits_per_r_val
) > (gen
.max
)())
58 unsigned terms_needed
= digits
/ bits_per_r_val
+ 1;
61 for (unsigned i
= 0; i
< terms_needed
; ++i
)
71 struct is_checked_cpp_int
: public boost::mpl::false_
73 template <unsigned MinBits
, unsigned MaxBits
, boost::multiprecision::cpp_integer_type SignType
, class Allocator
, boost::multiprecision::expression_template_option ET
>
74 struct is_checked_cpp_int
<boost::multiprecision::number
<boost::multiprecision::cpp_int_backend
<MinBits
, MaxBits
, SignType
, boost::multiprecision::checked
, Allocator
>, ET
> > : public boost::mpl::true_
78 typename
boost::enable_if_c
<boost::multiprecision::backends::is_fixed_precision
<typename
N::backend_type
>::value
&& !is_checked_cpp_int
<N
>::value
>::type
test(const N
&)
80 using namespace boost::multiprecision
;
82 static unsigned last_error_count
= 0;
88 // Test modular arithmetic by filling all the bits of our test type:
89 mpz_int f
= generate_random
<mpz_int
>(std::numeric_limits
<N
>::digits
+ 2);
90 mpz_int g
= generate_random
<mpz_int
>(std::numeric_limits
<N
>::digits
+ 2);
92 mask
<<= std::numeric_limits
<N
>::digits
;
96 mpz_int r
= (f
* g
) & mask
;
101 BOOST_CHECK_EQUAL(r1
.str(), r
.str());
103 if (last_error_count
!= (unsigned)boost::detail::test_errors())
105 last_error_count
= boost::detail::test_errors();
106 std::cout
<< std::hex
<< std::showbase
;
107 std::cout
<< f1
<< std::endl
;
108 std::cout
<< f
<< std::endl
;
109 std::cout
<< g1
<< std::endl
;
110 std::cout
<< g
<< std::endl
;
111 std::cout
<< r1
<< std::endl
;
112 std::cout
<< r
<< std::endl
;
115 static boost::random::mt19937 gen
;
116 boost::random::uniform_int_distribution
<> d(12, std::numeric_limits
<N
>::digits
);
117 f
= generate_random
<mpz_int
>(d(gen
));
118 g
= generate_random
<mpz_int
>(d(gen
));
124 BOOST_CHECK_EQUAL(r1
.str(), r
.str());
126 if (last_error_count
!= (unsigned)boost::detail::test_errors())
128 last_error_count
= boost::detail::test_errors();
129 std::cout
<< std::hex
<< std::showbase
;
130 std::cout
<< f1
<< std::endl
;
131 std::cout
<< f
<< std::endl
;
132 std::cout
<< g1
<< std::endl
;
133 std::cout
<< g
<< std::endl
;
134 std::cout
<< r1
<< std::endl
;
135 std::cout
<< r
<< std::endl
;
138 #ifndef CI_SUPPRESS_KNOWN_ISSUES
139 if (tim
.elapsed() > 200)
141 if (tim
.elapsed() > 25)
144 std::cout
<< "Timeout reached, aborting tests now....\n";
153 if (std::numeric_limits
<N
>::is_bounded
)
154 mask
= mpz_int((std::numeric_limits
<N
>::max
)());
158 unsigned upper_limit
= std::numeric_limits
<N
>::is_bounded
? std::numeric_limits
<N
>::digits
- 1 : 8192 * 2;
159 for (unsigned i
= 1024; i
< upper_limit
; i
*= 2)
169 if (std::numeric_limits
<N
>::is_bounded
)
173 BOOST_CHECK_EQUAL(y
.str(), b
.str());
175 if (last_error_count
!= (unsigned)boost::detail::test_errors())
177 last_error_count
= boost::detail::test_errors();
178 std::cout
<< std::hex
<< std::showbase
;
179 std::cout
<< a
<< std::endl
;
180 std::cout
<< x
<< std::endl
;
181 std::cout
<< b
<< std::endl
;
182 std::cout
<< y
<< std::endl
;
187 typename
boost::disable_if_c
<boost::multiprecision::backends::is_fixed_precision
<typename
N::backend_type
>::value
&& !is_checked_cpp_int
<N
>::value
>::type
test(const N
&)
189 using namespace boost::multiprecision
;
191 static unsigned last_error_count
= 0;
196 if (std::numeric_limits
<N
>::is_bounded
)
197 mask
= mpz_int((std::numeric_limits
<N
>::max
)());
200 // Test modular arithmetic by filling all the bits of our test type:
201 static boost::random::mt19937 gen
;
202 boost::random::uniform_int_distribution
<> d(12, std::numeric_limits
<N
>::is_bounded
? std::numeric_limits
<N
>::digits
: 100000);
203 mpz_int f
= generate_random
<mpz_int
>(d(gen
));
204 mpz_int g
= generate_random
<mpz_int
>(d(gen
));
206 if (std::numeric_limits
<N
>::is_bounded
)
212 BOOST_CHECK_EQUAL(r1
.str(), r
.str());
214 if (last_error_count
!= (unsigned)boost::detail::test_errors())
216 last_error_count
= boost::detail::test_errors();
217 std::cout
<< std::hex
<< std::showbase
;
218 std::cout
<< f1
<< std::endl
;
219 std::cout
<< f
<< std::endl
;
220 std::cout
<< g1
<< std::endl
;
221 std::cout
<< g
<< std::endl
;
222 std::cout
<< r1
<< std::endl
;
223 std::cout
<< r
<< std::endl
;
226 #ifndef CI_SUPPRESS_KNOWN_ISSUES
227 if (tim
.elapsed() > 200)
229 if (tim
.elapsed() > 25)
232 std::cout
<< "Timeout reached, aborting tests now....\n";
243 unsigned upper_limit
= std::numeric_limits
<N
>::is_bounded
? std::numeric_limits
<N
>::digits
- 1 : 8192 * 2;
244 for (unsigned i
= 1024; i
< upper_limit
; i
*= 2)
254 if (std::numeric_limits
<N
>::is_bounded
)
258 BOOST_CHECK_EQUAL(y
.str(), b
.str());
260 if (last_error_count
!= (unsigned)boost::detail::test_errors())
262 last_error_count
= boost::detail::test_errors();
263 std::cout
<< std::hex
<< std::showbase
;
264 std::cout
<< a
<< std::endl
;
265 std::cout
<< x
<< std::endl
;
266 std::cout
<< b
<< std::endl
;
267 std::cout
<< y
<< std::endl
;
274 using namespace boost::multiprecision
;
276 #if (TEST == 1) || (TEST == 0)
279 #if (TEST == 2) || (TEST == 0)
280 test(number
<cpp_int_backend
<8192, 8192, signed_magnitude
, unchecked
, void> >());
282 #if (TEST == 3) || (TEST == 0)
283 test(number
<cpp_int_backend
<8192, 8192, signed_magnitude
, unchecked
, std::allocator
<char> > >());
285 #if (TEST == 4) || (TEST == 0)
286 test(number
<cpp_int_backend
<8192, 8192, unsigned_magnitude
, unchecked
> >());
288 return boost::report_errors();