Chris@16
|
1 ///////////////////////////////////////////////////////////////
|
Chris@16
|
2 // Copyright 2013 John Maddock. Distributed under the Boost
|
Chris@16
|
3 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
|
Chris@16
|
5
|
Chris@16
|
6 #ifndef BOOST_MP_CPP_INT_SERIALIZE_HPP
|
Chris@16
|
7 #define BOOST_MP_CPP_INT_SERIALIZE_HPP
|
Chris@16
|
8
|
Chris@16
|
9 namespace boost {
|
Chris@16
|
10
|
Chris@16
|
11 namespace archive{
|
Chris@16
|
12
|
Chris@16
|
13 class binary_oarchive;
|
Chris@16
|
14 class binary_iarchive;
|
Chris@16
|
15
|
Chris@16
|
16 }
|
Chris@16
|
17
|
Chris@16
|
18 namespace serialization {
|
Chris@16
|
19
|
Chris@16
|
20 namespace mp = boost::multiprecision;
|
Chris@16
|
21
|
Chris@16
|
22 namespace cpp_int_detail{
|
Chris@16
|
23
|
Chris@16
|
24 using namespace boost::multiprecision;
|
Chris@16
|
25 using namespace boost::multiprecision::backends;
|
Chris@16
|
26
|
Chris@16
|
27 template <class T>
|
Chris@16
|
28 struct is_binary_archive : public mpl::false_ {};
|
Chris@16
|
29 template <>
|
Chris@16
|
30 struct is_binary_archive<boost::archive::binary_oarchive> : public mpl::true_ {};
|
Chris@16
|
31 template <>
|
Chris@16
|
32 struct is_binary_archive<boost::archive::binary_iarchive> : public mpl::true_ {};
|
Chris@16
|
33
|
Chris@16
|
34 //
|
Chris@16
|
35 // We have 8 serialization methods to fill out (and test), they are all permutations of:
|
Chris@16
|
36 // Load vs Store.
|
Chris@16
|
37 // Trivial or non-trivial cpp_int type.
|
Chris@16
|
38 // Binary or not archive.
|
Chris@16
|
39 //
|
Chris@16
|
40 template <class Archive, class Int>
|
Chris@16
|
41 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::false_ const&)
|
Chris@16
|
42 {
|
Chris@16
|
43 // Load.
|
Chris@16
|
44 // Non-trivial.
|
Chris@16
|
45 // Non binary.
|
Chris@16
|
46
|
Chris@16
|
47 bool s;
|
Chris@16
|
48 ar & s;
|
Chris@16
|
49 std::size_t limb_count;
|
Chris@16
|
50 std::size_t byte_count;
|
Chris@16
|
51 ar & byte_count;
|
Chris@16
|
52 limb_count = byte_count / sizeof(limb_type) + (byte_count % sizeof(limb_type) ? 1 : 0);
|
Chris@16
|
53 val.resize(limb_count, limb_count);
|
Chris@16
|
54 limb_type* pl = val.limbs();
|
Chris@16
|
55 for(std::size_t i = 0; i < limb_count; ++i)
|
Chris@16
|
56 {
|
Chris@16
|
57 pl[i] = 0;
|
Chris@16
|
58 for(std::size_t j = 0; (j < sizeof(limb_type)) && byte_count; ++j)
|
Chris@16
|
59 {
|
Chris@16
|
60 unsigned char byte;
|
Chris@16
|
61 ar & byte;
|
Chris@16
|
62 pl[i] |= static_cast<limb_type>(byte) << (j * CHAR_BIT);
|
Chris@16
|
63 --byte_count;
|
Chris@16
|
64 }
|
Chris@16
|
65 }
|
Chris@16
|
66 if(s != val.sign())
|
Chris@16
|
67 val.negate();
|
Chris@16
|
68 val.normalize();
|
Chris@16
|
69 }
|
Chris@16
|
70 template <class Archive, class Int>
|
Chris@16
|
71 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::false_ const&)
|
Chris@16
|
72 {
|
Chris@16
|
73 // Store.
|
Chris@16
|
74 // Non-trivial.
|
Chris@16
|
75 // Non binary.
|
Chris@16
|
76
|
Chris@16
|
77 bool s = val.sign();
|
Chris@16
|
78 ar & s;
|
Chris@16
|
79 limb_type* pl = val.limbs();
|
Chris@16
|
80 std::size_t limb_count = val.size();
|
Chris@16
|
81 std::size_t byte_count = limb_count * sizeof(limb_type);
|
Chris@16
|
82 ar & byte_count;
|
Chris@16
|
83
|
Chris@16
|
84 for(std::size_t i = 0; i < limb_count; ++i)
|
Chris@16
|
85 {
|
Chris@16
|
86 limb_type l = pl[i];
|
Chris@16
|
87 for(std::size_t j = 0; j < sizeof(limb_type); ++j)
|
Chris@16
|
88 {
|
Chris@16
|
89 unsigned char byte = static_cast<unsigned char>((l >> (j * CHAR_BIT)) & ((1u << CHAR_BIT) - 1));
|
Chris@16
|
90 ar & byte;
|
Chris@16
|
91 }
|
Chris@16
|
92 }
|
Chris@16
|
93 }
|
Chris@16
|
94 template <class Archive, class Int>
|
Chris@16
|
95 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::false_ const&)
|
Chris@16
|
96 {
|
Chris@16
|
97 // Load.
|
Chris@16
|
98 // Trivial.
|
Chris@16
|
99 // Non binary.
|
Chris@16
|
100 bool s;
|
Chris@16
|
101 typename Int::local_limb_type l = 0;
|
Chris@16
|
102 ar & s;
|
Chris@16
|
103 std::size_t byte_count;
|
Chris@16
|
104 ar & byte_count;
|
Chris@16
|
105 for(std::size_t i = 0; i < byte_count; ++i)
|
Chris@16
|
106 {
|
Chris@16
|
107 unsigned char b;
|
Chris@16
|
108 ar & b;
|
Chris@16
|
109 l |= static_cast<typename Int::local_limb_type>(b) << (i * CHAR_BIT);
|
Chris@16
|
110 }
|
Chris@16
|
111 *val.limbs() = l;
|
Chris@16
|
112 if(s != val.sign())
|
Chris@16
|
113 val.negate();
|
Chris@16
|
114 }
|
Chris@16
|
115 template <class Archive, class Int>
|
Chris@16
|
116 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::false_ const&)
|
Chris@16
|
117 {
|
Chris@16
|
118 // Store.
|
Chris@16
|
119 // Trivial.
|
Chris@16
|
120 // Non binary.
|
Chris@16
|
121 bool s = val.sign();
|
Chris@16
|
122 typename Int::local_limb_type l = *val.limbs();
|
Chris@16
|
123 ar & s;
|
Chris@16
|
124 std::size_t limb_count = sizeof(l);
|
Chris@16
|
125 ar & limb_count;
|
Chris@16
|
126 for(std::size_t i = 0; i < limb_count; ++i)
|
Chris@16
|
127 {
|
Chris@16
|
128 unsigned char b = static_cast<unsigned char>(static_cast<typename Int::local_limb_type>(l >> (i * CHAR_BIT)) & static_cast<typename Int::local_limb_type>((1u << CHAR_BIT) - 1));
|
Chris@16
|
129 ar & b;
|
Chris@16
|
130 }
|
Chris@16
|
131 }
|
Chris@16
|
132 template <class Archive, class Int>
|
Chris@16
|
133 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::true_ const&)
|
Chris@16
|
134 {
|
Chris@16
|
135 // Load.
|
Chris@16
|
136 // Non-trivial.
|
Chris@16
|
137 // Binary.
|
Chris@16
|
138 bool s;
|
Chris@16
|
139 std::size_t c;
|
Chris@16
|
140 ar & s;
|
Chris@16
|
141 ar & c;
|
Chris@16
|
142 val.resize(c, c);
|
Chris@16
|
143 ar.load_binary(val.limbs(), c * sizeof(limb_type));
|
Chris@16
|
144 if(s != val.sign())
|
Chris@16
|
145 val.negate();
|
Chris@16
|
146 val.normalize();
|
Chris@16
|
147 }
|
Chris@16
|
148 template <class Archive, class Int>
|
Chris@16
|
149 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::true_ const&)
|
Chris@16
|
150 {
|
Chris@16
|
151 // Store.
|
Chris@16
|
152 // Non-trivial.
|
Chris@16
|
153 // Binary.
|
Chris@16
|
154 bool s = val.sign();
|
Chris@16
|
155 std::size_t c = val.size();
|
Chris@16
|
156 ar & s;
|
Chris@16
|
157 ar & c;
|
Chris@16
|
158 ar.save_binary(val.limbs(), c * sizeof(limb_type));
|
Chris@16
|
159 }
|
Chris@16
|
160 template <class Archive, class Int>
|
Chris@16
|
161 void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::true_ const&)
|
Chris@16
|
162 {
|
Chris@16
|
163 // Load.
|
Chris@16
|
164 // Trivial.
|
Chris@16
|
165 // Binary.
|
Chris@16
|
166 bool s;
|
Chris@16
|
167 ar & s;
|
Chris@16
|
168 ar.load_binary(val.limbs(), sizeof(*val.limbs()));
|
Chris@16
|
169 if(s != val.sign())
|
Chris@16
|
170 val.negate();
|
Chris@16
|
171 }
|
Chris@16
|
172 template <class Archive, class Int>
|
Chris@16
|
173 void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::true_ const&)
|
Chris@16
|
174 {
|
Chris@16
|
175 // Store.
|
Chris@16
|
176 // Trivial.
|
Chris@16
|
177 // Binary.
|
Chris@16
|
178 bool s = val.sign();
|
Chris@16
|
179 ar & s;
|
Chris@16
|
180 ar.save_binary(val.limbs(), sizeof(*val.limbs()));
|
Chris@16
|
181 }
|
Chris@16
|
182
|
Chris@16
|
183 }
|
Chris@16
|
184
|
Chris@16
|
185 template<class Archive, unsigned MinBits, unsigned MaxBits, mp::cpp_integer_type SignType, mp::cpp_int_check_type Checked, class Allocator>
|
Chris@16
|
186 void serialize(Archive & ar, mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& val, const unsigned int /*version*/)
|
Chris@16
|
187 {
|
Chris@16
|
188 typedef typename Archive::is_saving save_tag;
|
Chris@16
|
189 typedef mpl::bool_<mp::backends::is_trivial_cpp_int<mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value> trivial_tag;
|
Chris@16
|
190 typedef typename cpp_int_detail::is_binary_archive<Archive>::type binary_tag;
|
Chris@16
|
191
|
Chris@16
|
192 // Just dispatch to the correct method:
|
Chris@16
|
193 cpp_int_detail::do_serialize(ar, val, save_tag(), trivial_tag(), binary_tag());
|
Chris@16
|
194 }
|
Chris@16
|
195
|
Chris@16
|
196 }} // namespaces
|
Chris@16
|
197
|
Chris@16
|
198 #endif // BOOST_MP_CPP_INT_SERIALIZE_HPP
|
Chris@16
|
199
|