]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/multiprecision/test/test_cpp_int_import_export.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / multiprecision / test / test_cpp_int_import_export.cpp
1 // Copyright John Maddock 2015.
2
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)
7
8 #ifdef _MSC_VER
9 # define _SCL_SECURE_NO_WARNINGS
10 #endif
11
12 #include <boost/multiprecision/cpp_int.hpp>
13
14 #include <boost/algorithm/string/case_conv.hpp>
15 #include <boost/random/mersenne_twister.hpp>
16 #include <boost/random/uniform_int.hpp>
17 #include "test.hpp"
18 #include <iostream>
19 #include <iomanip>
20
21 #ifdef BOOST_MSVC
22 #pragma warning(disable:4127)
23 #endif
24 template <class T>
25 struct unchecked_type { typedef T type; };
26
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> >
29 {
30 typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, boost::multiprecision::unchecked, Allocator>, ExpressionTemplates> type;
31 };
32
33
34 template <class T>
35 T generate_random()
36 {
37 typedef typename unchecked_type<T>::type unchecked_T;
38
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;
40
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)
46 {
47 val *= (gen.max)();
48 val += gen();
49 }
50 return val;
51 }
52
53 template <class T>
54 void test_round_trip_neg(T val, const boost::mpl::true_&)
55 {
56 // Try some negative values:
57 std::vector<unsigned char> cv;
58 T newval;
59 val = -val;
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);
63 }
64
65 template <class T>
66 void test_round_trip_neg(const T&, const boost::mpl::false_&)
67 {
68 }
69
70 template <class T>
71 void test_round_trip(T val)
72 {
73 std::vector<unsigned char> cv;
74 export_bits(val, std::back_inserter(cv), 8);
75 T newval;
76 import_bits(newval, cv.begin(), cv.end());
77 BOOST_CHECK_EQUAL(val, newval);
78 // Should get the same value if we reverse the bytes:
79 std::reverse(cv.begin(), cv.end());
80 newval = 0;
81 import_bits(newval, cv.begin(), cv.end(), 8, false);
82 BOOST_CHECK_EQUAL(val, newval);
83 // Also try importing via pointers as these may memcpy:
84 newval = 0;
85 import_bits(newval, &cv[0], &cv[0] + cv.size(), 8, false);
86 BOOST_CHECK_EQUAL(val, newval);
87
88 cv.clear();
89 export_bits(val, std::back_inserter(cv), 8, false);
90 import_bits(newval, cv.begin(), cv.end(), 8, false);
91 BOOST_CHECK_EQUAL(val, newval);
92 std::reverse(cv.begin(), cv.end());
93 newval = 0;
94 import_bits(newval, cv.begin(), cv.end(), 8, true);
95 BOOST_CHECK_EQUAL(val, newval);
96
97 std::vector<boost::uintmax_t> bv;
98 export_bits(val, std::back_inserter(bv), std::numeric_limits<boost::uintmax_t>::digits);
99 import_bits(newval, bv.begin(), bv.end());
100 BOOST_CHECK_EQUAL(val, newval);
101 // Should get the same value if we reverse the values:
102 std::reverse(bv.begin(), bv.end());
103 newval = 0;
104 import_bits(newval, bv.begin(), bv.end(), std::numeric_limits<boost::uintmax_t>::digits, false);
105 BOOST_CHECK_EQUAL(val, newval);
106 // Also try importing via pointers as these may memcpy:
107 newval = 0;
108 import_bits(newval, &bv[0], &bv[0] + bv.size(), std::numeric_limits<boost::uintmax_t>::digits, false);
109 BOOST_CHECK_EQUAL(val, newval);
110
111 bv.clear();
112 export_bits(val, std::back_inserter(bv), std::numeric_limits<boost::uintmax_t>::digits, false);
113 import_bits(newval, bv.begin(), bv.end(), std::numeric_limits<boost::uintmax_t>::digits, false);
114 BOOST_CHECK_EQUAL(val, newval);
115 //
116 // Try with an unconventional number of bits, to model some machine with guard bits:
117 //
118 bv.clear();
119 export_bits(val, std::back_inserter(bv), std::numeric_limits<boost::uintmax_t>::digits - 3);
120 import_bits(newval, bv.begin(), bv.end(), std::numeric_limits<boost::uintmax_t>::digits - 3);
121 BOOST_CHECK_EQUAL(val, newval);
122
123 bv.clear();
124 export_bits(val, std::back_inserter(bv), std::numeric_limits<boost::uintmax_t>::digits - 3, false);
125 import_bits(newval, bv.begin(), bv.end(), std::numeric_limits<boost::uintmax_t>::digits - 3, false);
126 BOOST_CHECK_EQUAL(val, newval);
127
128 cv.clear();
129 export_bits(val, std::back_inserter(cv), 6);
130 import_bits(newval, cv.begin(), cv.end(), 6);
131 BOOST_CHECK_EQUAL(val, newval);
132
133 cv.clear();
134 export_bits(val, std::back_inserter(cv), 6, false);
135 import_bits(newval, cv.begin(), cv.end(), 6, false);
136 BOOST_CHECK_EQUAL(val, newval);
137
138 test_round_trip_neg(val, boost::mpl::bool_<std::numeric_limits<T>::is_signed>());
139 }
140
141 template <class T>
142 void test_round_trip()
143 {
144 std::cout << std::hex;
145 std::cerr << std::hex;
146 for(unsigned i = 0; i < 1000; ++i)
147 {
148 T val = generate_random<T>();
149 test_round_trip(val);
150 }
151 //
152 // Bug cases.
153 // See https://github.com/boostorg/multiprecision/issues/21
154 T bug(1);
155 bug << std::numeric_limits<T>::digits - 1;
156 --bug;
157 test_round_trip(bug);
158 }
159
160 int main()
161 {
162 test_round_trip<boost::multiprecision::cpp_int>();
163 test_round_trip<boost::multiprecision::checked_int1024_t>();
164 test_round_trip<boost::multiprecision::checked_uint512_t >();
165 test_round_trip<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<64, 64, boost::multiprecision::unsigned_magnitude, boost::multiprecision::checked, void> > >();
166 test_round_trip<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<23, 23, boost::multiprecision::unsigned_magnitude, boost::multiprecision::checked, void> > >();
167 return boost::report_errors();
168 }
169