serialize.hpp 5.9 KB

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