From 8d6ac4e63198d8bd403fb79bb5a360d6f6644a35 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Mon, 5 Aug 2013 12:22:53 +0000 Subject: [PATCH] Add missing serialization file [SVN r85213] --- .../multiprecision/cpp_int/serialize.hpp | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 include/boost/multiprecision/cpp_int/serialize.hpp diff --git a/include/boost/multiprecision/cpp_int/serialize.hpp b/include/boost/multiprecision/cpp_int/serialize.hpp new file mode 100644 index 00000000..d4c8b955 --- /dev/null +++ b/include/boost/multiprecision/cpp_int/serialize.hpp @@ -0,0 +1,201 @@ +/////////////////////////////////////////////////////////////// +// 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); ++j) + { + limb_type byte; + ar & byte; + byte <<= (j * CHAR_BIT); + pl[i] |= byte; + } + } + 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_count); + 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 byte = (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 limb_count; + ar & limb_count; + for(std::size_t i = 0; i < limb_count; ++i) + { + typename Int::local_limb_type b; + ar & b; + l |= 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) + { + typename Int::local_limb_type b = 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); + for(unsigned i = 0; i < c; ++i) + ar & val.limbs()[i]; + 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; + for(unsigned i = 0; i < c; ++i) + ar & val.limbs()[i]; +} +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 & *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 & *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 +