1 // Copyright John Maddock 2015.
3 // Use, modification and distribution are subject to the
4 // Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt
6 // or copy at http://www.boost.org/LICENSE_1_0.txt)
9 # define _SCL_SECURE_NO_WARNINGS
12 #include <boost/multiprecision/cpp_int.hpp>
14 #include <boost/algorithm/string/case_conv.hpp>
15 #include <boost/random/mersenne_twister.hpp>
16 #include <boost/random/uniform_int.hpp>
22 #pragma warning(disable:4127)
25 struct unchecked_type
{ typedef T type
; };
27 template <unsigned MinBits
, unsigned MaxBits
, boost::multiprecision::cpp_integer_type SignType
, boost::multiprecision::cpp_int_check_type Checked
, class Allocator
, boost::multiprecision::expression_template_option ExpressionTemplates
>
28 struct unchecked_type
<boost::multiprecision::number
<boost::multiprecision::cpp_int_backend
<MinBits
, MaxBits
, SignType
, Checked
, Allocator
>, ExpressionTemplates
> >
30 typedef boost::multiprecision::number
<boost::multiprecision::cpp_int_backend
<MinBits
, MaxBits
, SignType
, boost::multiprecision::unchecked
, Allocator
>, ExpressionTemplates
> type
;
37 typedef typename unchecked_type
<T
>::type unchecked_T
;
39 static const unsigned limbs
= std::numeric_limits
<T
>::is_specialized
&& std::numeric_limits
<T
>::is_bounded
? std::numeric_limits
<T
>::digits
/ std::numeric_limits
<unsigned>::digits
+ 3 : 20;
41 static boost::random::uniform_int_distribution
<unsigned> ui(0, limbs
);
42 static boost::random::mt19937 gen
;
43 unchecked_T val
= gen();
44 unsigned lim
= ui(gen
);
45 for(unsigned i
= 0; i
< lim
; ++i
)
54 void test_round_trip_neg(T val
, const boost::mpl::true_
&)
56 // Try some negative values:
57 std::vector
<unsigned char> cv
;
60 export_bits(val
, std::back_inserter(cv
), 8, false);
61 import_bits(newval
, cv
.begin(), cv
.end(), 8, false);
62 BOOST_CHECK_EQUAL(-val
, newval
);
66 void test_round_trip_neg(const T
&, const boost::mpl::false_
&)
71 void test_round_trip()
73 std::cout
<< std::hex
;
74 std::cerr
<< std::hex
;
75 for(unsigned i
= 0; i
< 1000; ++i
)
77 T val
= generate_random
<T
>();
78 std::vector
<unsigned char> cv
;
79 export_bits(val
, std::back_inserter(cv
), 8);
81 import_bits(newval
, cv
.begin(), cv
.end());
82 BOOST_CHECK_EQUAL(val
, newval
);
83 // Should get the same value if we reverse the bytes:
84 std::reverse(cv
.begin(), cv
.end());
86 import_bits(newval
, cv
.begin(), cv
.end(), 8, false);
87 BOOST_CHECK_EQUAL(val
, newval
);
88 // Also try importing via pointers as these may memcpy:
90 import_bits(newval
, &cv
[0], &cv
[0] + cv
.size(), 8, false);
91 BOOST_CHECK_EQUAL(val
, newval
);
94 export_bits(val
, std::back_inserter(cv
), 8, false);
95 import_bits(newval
, cv
.begin(), cv
.end(), 8, false);
96 BOOST_CHECK_EQUAL(val
, newval
);
97 std::reverse(cv
.begin(), cv
.end());
99 import_bits(newval
, cv
.begin(), cv
.end(), 8, true);
100 BOOST_CHECK_EQUAL(val
, newval
);
102 std::vector
<boost::uintmax_t> bv
;
103 export_bits(val
, std::back_inserter(bv
), std::numeric_limits
<boost::uintmax_t>::digits
);
104 import_bits(newval
, bv
.begin(), bv
.end());
105 BOOST_CHECK_EQUAL(val
, newval
);
106 // Should get the same value if we reverse the values:
107 std::reverse(bv
.begin(), bv
.end());
109 import_bits(newval
, bv
.begin(), bv
.end(), std::numeric_limits
<boost::uintmax_t>::digits
, false);
110 BOOST_CHECK_EQUAL(val
, newval
);
111 // Also try importing via pointers as these may memcpy:
113 import_bits(newval
, &bv
[0], &bv
[0] + bv
.size(), std::numeric_limits
<boost::uintmax_t>::digits
, false);
114 BOOST_CHECK_EQUAL(val
, newval
);
117 export_bits(val
, std::back_inserter(bv
), std::numeric_limits
<boost::uintmax_t>::digits
, false);
118 import_bits(newval
, bv
.begin(), bv
.end(), std::numeric_limits
<boost::uintmax_t>::digits
, false);
119 BOOST_CHECK_EQUAL(val
, newval
);
121 // Try with an unconventional number of bits, to model some machine with guard bits:
124 export_bits(val
, std::back_inserter(bv
), std::numeric_limits
<boost::uintmax_t>::digits
- 3);
125 import_bits(newval
, bv
.begin(), bv
.end(), std::numeric_limits
<boost::uintmax_t>::digits
- 3);
126 BOOST_CHECK_EQUAL(val
, newval
);
129 export_bits(val
, std::back_inserter(bv
), std::numeric_limits
<boost::uintmax_t>::digits
- 3, false);
130 import_bits(newval
, bv
.begin(), bv
.end(), std::numeric_limits
<boost::uintmax_t>::digits
- 3, false);
131 BOOST_CHECK_EQUAL(val
, newval
);
134 export_bits(val
, std::back_inserter(cv
), 6);
135 import_bits(newval
, cv
.begin(), cv
.end(), 6);
136 BOOST_CHECK_EQUAL(val
, newval
);
139 export_bits(val
, std::back_inserter(cv
), 6, false);
140 import_bits(newval
, cv
.begin(), cv
.end(), 6, false);
141 BOOST_CHECK_EQUAL(val
, newval
);
143 test_round_trip_neg(val
, boost::mpl::bool_
<std::numeric_limits
<T
>::is_signed
>());
149 test_round_trip
<boost::multiprecision::cpp_int
>();
150 test_round_trip
<boost::multiprecision::checked_int1024_t
>();
151 test_round_trip
<boost::multiprecision::checked_uint512_t
>();
152 test_round_trip
<boost::multiprecision::number
<boost::multiprecision::cpp_int_backend
<64, 64, boost::multiprecision::unsigned_magnitude
, boost::multiprecision::checked
, void> > >();
153 test_round_trip
<boost::multiprecision::number
<boost::multiprecision::cpp_int_backend
<23, 23, boost::multiprecision::unsigned_magnitude
, boost::multiprecision::checked
, void> > >();
154 return boost::report_errors();