diff options
Diffstat (limited to 'boost/multiprecision/cpp_int/serialize.hpp')
-rw-r--r-- | boost/multiprecision/cpp_int/serialize.hpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/boost/multiprecision/cpp_int/serialize.hpp b/boost/multiprecision/cpp_int/serialize.hpp new file mode 100644 index 0000000000..bdf4758a6e --- /dev/null +++ b/boost/multiprecision/cpp_int/serialize.hpp @@ -0,0 +1,199 @@ +/////////////////////////////////////////////////////////////// +// 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 <class T> +struct is_binary_archive : public mpl::false_ {}; +template <> +struct is_binary_archive<boost::archive::binary_oarchive> : public mpl::true_ {}; +template <> +struct is_binary_archive<boost::archive::binary_iarchive> : 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 <class Archive, class Int> +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<limb_type>(byte) << (j * CHAR_BIT); + --byte_count; + } + } + if(s != val.sign()) + val.negate(); + val.normalize(); +} +template <class Archive, class Int> +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<unsigned char>((l >> (j * CHAR_BIT)) & ((1u << CHAR_BIT) - 1)); + ar & byte; + } + } +} +template <class Archive, class Int> +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<typename Int::local_limb_type>(b) << (i * CHAR_BIT); + } + *val.limbs() = l; + if(s != val.sign()) + val.negate(); +} +template <class Archive, class Int> +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<unsigned char>(static_cast<typename Int::local_limb_type>(l >> (i * CHAR_BIT)) & static_cast<typename Int::local_limb_type>((1u << CHAR_BIT) - 1)); + ar & b; + } +} +template <class Archive, class Int> +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 <class Archive, class Int> +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 <class Archive, class Int> +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 <class Archive, class Int> +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<class Archive, unsigned MinBits, unsigned MaxBits, mp::cpp_integer_type SignType, mp::cpp_int_check_type Checked, class Allocator> +void serialize(Archive & ar, mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& val, const unsigned int /*version*/) +{ + typedef typename Archive::is_saving save_tag; + typedef mpl::bool_<mp::backends::is_trivial_cpp_int<mp::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value> trivial_tag; + typedef typename cpp_int_detail::is_binary_archive<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 + |