]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/multiprecision/test/test_cpp_int_import_export.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / multiprecision / test / test_cpp_int_import_export.cpp
CommitLineData
7c673cae
FG
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
92f5a8d4 9#define _SCL_SECURE_NO_WARNINGS
7c673cae
FG
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
92f5a8d4 22#pragma warning(disable : 4127)
7c673cae
FG
23#endif
24template <class T>
92f5a8d4
TL
25struct unchecked_type
26{
27 typedef T type;
28};
7c673cae 29
1e59de90 30template <std::size_t MinBits, std::size_t MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
7c673cae
FG
31struct unchecked_type<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >
32{
33 typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, boost::multiprecision::unchecked, Allocator>, ExpressionTemplates> type;
34};
35
7c673cae
FG
36template <class T>
37T generate_random()
38{
39 typedef typename unchecked_type<T>::type unchecked_T;
40
41 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;
42
43 static boost::random::uniform_int_distribution<unsigned> ui(0, limbs);
92f5a8d4
TL
44 static boost::random::mt19937 gen;
45 unchecked_T val = gen();
46 unsigned lim = ui(gen);
47 for (unsigned i = 0; i < lim; ++i)
7c673cae
FG
48 {
49 val *= (gen.max)();
50 val += gen();
51 }
52 return val;
53}
54
55template <class T>
1e59de90 56void test_round_trip_neg(T val, const std::integral_constant<bool, true>&)
7c673cae
FG
57{
58 // Try some negative values:
59 std::vector<unsigned char> cv;
92f5a8d4 60 T newval;
7c673cae
FG
61 val = -val;
62 export_bits(val, std::back_inserter(cv), 8, false);
63 import_bits(newval, cv.begin(), cv.end(), 8, false);
64 BOOST_CHECK_EQUAL(-val, newval);
65}
66
67template <class T>
1e59de90 68void test_round_trip_neg(const T&, const std::integral_constant<bool, false>&)
7c673cae
FG
69{
70}
71
b32b8144
FG
72template <class T>
73void test_round_trip(T val)
74{
75 std::vector<unsigned char> cv;
76 export_bits(val, std::back_inserter(cv), 8);
77 T newval;
78 import_bits(newval, cv.begin(), cv.end());
79 BOOST_CHECK_EQUAL(val, newval);
80 // Should get the same value if we reverse the bytes:
81 std::reverse(cv.begin(), cv.end());
82 newval = 0;
83 import_bits(newval, cv.begin(), cv.end(), 8, false);
84 BOOST_CHECK_EQUAL(val, newval);
85 // Also try importing via pointers as these may memcpy:
86 newval = 0;
87 import_bits(newval, &cv[0], &cv[0] + cv.size(), 8, false);
88 BOOST_CHECK_EQUAL(val, newval);
89
90 cv.clear();
91 export_bits(val, std::back_inserter(cv), 8, false);
92 import_bits(newval, cv.begin(), cv.end(), 8, false);
93 BOOST_CHECK_EQUAL(val, newval);
94 std::reverse(cv.begin(), cv.end());
95 newval = 0;
96 import_bits(newval, cv.begin(), cv.end(), 8, true);
97 BOOST_CHECK_EQUAL(val, newval);
98
1e59de90
TL
99 std::vector<std::uintmax_t> bv;
100 export_bits(val, std::back_inserter(bv), std::numeric_limits<std::uintmax_t>::digits);
b32b8144
FG
101 import_bits(newval, bv.begin(), bv.end());
102 BOOST_CHECK_EQUAL(val, newval);
103 // Should get the same value if we reverse the values:
104 std::reverse(bv.begin(), bv.end());
105 newval = 0;
1e59de90 106 import_bits(newval, bv.begin(), bv.end(), std::numeric_limits<std::uintmax_t>::digits, false);
b32b8144
FG
107 BOOST_CHECK_EQUAL(val, newval);
108 // Also try importing via pointers as these may memcpy:
109 newval = 0;
1e59de90 110 import_bits(newval, &bv[0], &bv[0] + bv.size(), std::numeric_limits<std::uintmax_t>::digits, false);
b32b8144
FG
111 BOOST_CHECK_EQUAL(val, newval);
112
113 bv.clear();
1e59de90
TL
114 export_bits(val, std::back_inserter(bv), std::numeric_limits<std::uintmax_t>::digits, false);
115 import_bits(newval, bv.begin(), bv.end(), std::numeric_limits<std::uintmax_t>::digits, false);
b32b8144
FG
116 BOOST_CHECK_EQUAL(val, newval);
117 //
118 // Try with an unconventional number of bits, to model some machine with guard bits:
119 //
120 bv.clear();
1e59de90
TL
121 export_bits(val, std::back_inserter(bv), std::numeric_limits<std::uintmax_t>::digits - 3);
122 import_bits(newval, bv.begin(), bv.end(), std::numeric_limits<std::uintmax_t>::digits - 3);
b32b8144
FG
123 BOOST_CHECK_EQUAL(val, newval);
124
125 bv.clear();
1e59de90
TL
126 export_bits(val, std::back_inserter(bv), std::numeric_limits<std::uintmax_t>::digits - 3, false);
127 import_bits(newval, bv.begin(), bv.end(), std::numeric_limits<std::uintmax_t>::digits - 3, false);
b32b8144
FG
128 BOOST_CHECK_EQUAL(val, newval);
129
130 cv.clear();
131 export_bits(val, std::back_inserter(cv), 6);
132 import_bits(newval, cv.begin(), cv.end(), 6);
133 BOOST_CHECK_EQUAL(val, newval);
134
135 cv.clear();
136 export_bits(val, std::back_inserter(cv), 6, false);
137 import_bits(newval, cv.begin(), cv.end(), 6, false);
138 BOOST_CHECK_EQUAL(val, newval);
139
1e59de90 140 test_round_trip_neg(val, std::integral_constant<bool, std::numeric_limits<T>::is_signed>());
b32b8144
FG
141}
142
7c673cae
FG
143template <class T>
144void test_round_trip()
145{
146 std::cout << std::hex;
147 std::cerr << std::hex;
92f5a8d4 148 for (unsigned i = 0; i < 1000; ++i)
7c673cae
FG
149 {
150 T val = generate_random<T>();
b32b8144 151 test_round_trip(val);
7c673cae 152 }
b32b8144 153 //
92f5a8d4 154 // Bug cases.
b32b8144
FG
155 // See https://github.com/boostorg/multiprecision/issues/21
156 T bug(1);
157 bug << std::numeric_limits<T>::digits - 1;
158 --bug;
159 test_round_trip(bug);
7c673cae
FG
160}
161
162int main()
163{
164 test_round_trip<boost::multiprecision::cpp_int>();
165 test_round_trip<boost::multiprecision::checked_int1024_t>();
92f5a8d4 166 test_round_trip<boost::multiprecision::checked_uint512_t>();
7c673cae
FG
167 test_round_trip<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<64, 64, boost::multiprecision::unsigned_magnitude, boost::multiprecision::checked, void> > >();
168 test_round_trip<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<23, 23, boost::multiprecision::unsigned_magnitude, boost::multiprecision::checked, void> > >();
169 return boost::report_errors();
170}