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