/////////////////////////////////////////////////////////////// // Copyright 2013 John Maddock. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ #ifndef BOOST_MP_CPP_INT_SERIALIZE_HPP #define BOOST_MP_CPP_INT_SERIALIZE_HPP namespace boost { namespace archive{ class binary_oarchive; class binary_iarchive; } namespace serialization { namespace mp = boost::multiprecision; namespace cpp_int_detail{ using namespace boost::multiprecision; using namespace boost::multiprecision::backends; template struct is_binary_archive : public mpl::false_ {}; template <> struct is_binary_archive : public mpl::true_ {}; template <> struct is_binary_archive : public mpl::true_ {}; // // We have 8 serialization methods to fill out (and test), they are all permutations of: // Load vs Store. // Trivial or non-trivial cpp_int type. // Binary or not archive. // template void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::false_ const&) { // Load. // Non-trivial. // Non binary. bool s; ar & s; std::size_t limb_count; std::size_t byte_count; ar & byte_count; limb_count = byte_count / sizeof(limb_type) + (byte_count % sizeof(limb_type) ? 1 : 0); val.resize(limb_count, limb_count); limb_type* pl = val.limbs(); for(std::size_t i = 0; i < limb_count; ++i) { pl[i] = 0; for(std::size_t j = 0; (j < sizeof(limb_type)) && byte_count; ++j) { unsigned char byte; ar & byte; pl[i] |= static_cast(byte) << (j * CHAR_BIT); --byte_count; } } if(s != val.sign()) val.negate(); val.normalize(); } template void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::false_ const&) { // Store. // Non-trivial. // Non binary. bool s = val.sign(); ar & s; limb_type* pl = val.limbs(); std::size_t limb_count = val.size(); std::size_t byte_count = limb_count * sizeof(limb_type); ar & byte_count; for(std::size_t i = 0; i < limb_count; ++i) { limb_type l = pl[i]; for(std::size_t j = 0; j < sizeof(limb_type); ++j) { unsigned char byte = static_cast((l >> (j * CHAR_BIT)) & ((1u << CHAR_BIT) - 1)); ar & byte; } } } template void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::false_ const&) { // Load. // Trivial. // Non binary. bool s; typename Int::local_limb_type l = 0; ar & s; std::size_t byte_count; ar & byte_count; for(std::size_t i = 0; i < byte_count; ++i) { unsigned char b; ar & b; l |= static_cast(b) << (i * CHAR_BIT); } *val.limbs() = l; if(s != val.sign()) val.negate(); } template void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::false_ const&) { // Store. // Trivial. // Non binary. bool s = val.sign(); typename Int::local_limb_type l = *val.limbs(); ar & s; std::size_t limb_count = sizeof(l); ar & limb_count; for(std::size_t i = 0; i < limb_count; ++i) { unsigned char b = static_cast(static_cast(l >> (i * CHAR_BIT)) & static_cast((1u << CHAR_BIT) - 1)); ar & b; } } template void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::true_ const&) { // Load. // Non-trivial. // Binary. bool s; std::size_t c; ar & s; ar & c; val.resize(c, c); ar.load_binary(val.limbs(), c * sizeof(limb_type)); if(s != val.sign()) val.negate(); val.normalize(); } template void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::true_ const&) { // Store. // Non-trivial. // Binary. bool s = val.sign(); std::size_t c = val.size(); ar & s; ar & c; ar.save_binary(val.limbs(), c * sizeof(limb_type)); } template void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&, mpl::true_ const&) { // Load. // Trivial. // Binary. bool s; ar & s; ar.load_binary(val.limbs(), sizeof(*val.limbs())); if(s != val.sign()) val.negate(); } template void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, mpl::true_ const&) { // Store. // Trivial. // Binary. bool s = val.sign(); ar & s; ar.save_binary(val.limbs(), sizeof(*val.limbs())); } } template void serialize(Archive & ar, mp::cpp_int_backend& val, const unsigned int /*version*/) { typedef typename Archive::is_saving save_tag; typedef mpl::bool_ >::value> trivial_tag; typedef typename cpp_int_detail::is_binary_archive::type binary_tag; // Just dispatch to the correct method: cpp_int_detail::do_serialize(ar, val, save_tag(), trivial_tag(), binary_tag()); } }} // namespaces #endif // BOOST_MP_CPP_INT_SERIALIZE_HPP