diff --git a/include/boost/multiprecision/debug_adaptor.hpp b/include/boost/multiprecision/debug_adaptor.hpp index 4e3da69d..4dc14aad 100644 --- a/include/boost/multiprecision/debug_adaptor.hpp +++ b/include/boost/multiprecision/debug_adaptor.hpp @@ -108,6 +108,14 @@ public: { return m_value; } + template + void serialize(Archive& ar, const unsigned int /*version*/) + { + ar & m_value; + typedef typename Archive::is_loading tag; + if(tag::value) + update_view(); + } }; template diff --git a/include/boost/multiprecision/detail/float_string_cvt.hpp b/include/boost/multiprecision/detail/float_string_cvt.hpp index 6c1f323e..48bb68bf 100644 --- a/include/boost/multiprecision/detail/float_string_cvt.hpp +++ b/include/boost/multiprecision/detail/float_string_cvt.hpp @@ -54,7 +54,7 @@ std::string convert_to_string(Backend b, std::streamsize digits, std::ios_base:: std::string result; bool iszero = false; bool isneg = false; - exponent_type expon; + exponent_type expon = 0; std::streamsize org_digits = digits; BOOST_ASSERT(digits > 0); diff --git a/include/boost/multiprecision/float128.hpp b/include/boost/multiprecision/float128.hpp index 38ee01e2..a14d9285 100644 --- a/include/boost/multiprecision/float128.hpp +++ b/include/boost/multiprecision/float128.hpp @@ -17,11 +17,13 @@ extern "C" { #include } +typedef __float128 float128_type; + #else #include -typedef _Quad __float128; +typedef _Quad float128_type; extern "C" { _Quad __ldexpq(_Quad, int); @@ -95,7 +97,7 @@ using backends::float128_backend; template<> struct number_category : public mpl::int_ {}; template<> -struct number_category<__float128> : public mpl::int_ {}; +struct number_category : public mpl::int_ {}; typedef number float128; @@ -110,7 +112,7 @@ struct float128_backend typedef int exponent_type; private: - __float128 m_value; + float128_type m_value; public: BOOST_CONSTEXPR float128_backend() : m_value(0) {} BOOST_CONSTEXPR float128_backend(const float128_backend& o) : m_value(o.m_value) {} @@ -120,10 +122,10 @@ public: return *this; } template - BOOST_CONSTEXPR float128_backend(const T& i, const typename enable_if_c::value>::type* = 0) + BOOST_CONSTEXPR float128_backend(const T& i, const typename enable_if_c::value>::type* = 0) : m_value(i) {} template - typename enable_if_c::value || is_convertible::value, float128_backend&>::type operator = (const T& i) + typename enable_if_c::value || is_convertible::value, float128_backend&>::type operator = (const T& i) { m_value = i; return *this; @@ -176,7 +178,7 @@ public: v = quadmath_snprintf (&buf2[0], v_max + 3, format.c_str(), digits, m_value); if(v >= v_max + 3) { - BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of __float128 failed.")); + BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of float128_type failed.")); } return &buf2[0]; } @@ -198,11 +200,11 @@ public: { return m_value == i ? 0 : m_value < i ? -1 : 1; } - __float128& value() + float128_type& value() { return m_value; } - const __float128& value()const + const float128_type& value()const { return m_value; } @@ -442,6 +444,62 @@ inline void eval_atan2(float128_backend& result, const float128_backend& a, cons }} // namespaces +namespace boost{ +namespace archive{ + +class binary_oarchive; +class binary_iarchive; + +} + +namespace serialization{ namespace float128_detail{ + +template +void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::false_&, const mpl::false_&) +{ + // saving + // non-binary + std::string s(val.str(0, std::ios_base::scientific)); + ar & s; +} +template +void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::true_&, const mpl::false_&) +{ + // loading + // non-binary + std::string s; + ar & s; + val = s.c_str(); +} + +template +void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::false_&, const mpl::true_&) +{ + // saving + // binary + ar.save_binary(&val, sizeof(val)); +} +template +void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::true_&, const mpl::true_&) +{ + // loading + // binary + ar.load_binary(&val, sizeof(val)); +} + +} // detail + +template +void serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, unsigned int /*version*/) +{ + typedef typename Archive::is_loading load_tag; + typedef typename mpl::bool_::value || boost::is_same::value> binary_tag; + + float128_detail::do_serialize(ar, val, load_tag(), binary_tag()); +} + +}} + namespace std{ template diff --git a/include/boost/multiprecision/logged_adaptor.hpp b/include/boost/multiprecision/logged_adaptor.hpp index 9684f603..2045f277 100644 --- a/include/boost/multiprecision/logged_adaptor.hpp +++ b/include/boost/multiprecision/logged_adaptor.hpp @@ -132,6 +132,13 @@ public: { return m_value; } + template + void serialize(Archive& ar, const unsigned int /*version*/) + { + log_prefix_event(m_value, "serialize"); + ar & m_value; + log_postfix_event(m_value, "serialize"); + } }; template diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1ed9558b..9ee379c6 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -577,8 +577,10 @@ run test_cpp_int_serial.cpp ../../serialization/build//boost_serialization : : : run test_cpp_int_serial.cpp ../../serialization/build//boost_serialization : : : release TEST4 : test_cpp_int_serial_4 ; run test_cpp_int_deserial.cpp ../../serialization/build//boost_serialization : : : release ; run test_cpp_rat_serial.cpp ../../serialization/build//boost_serialization : : : release ; +run test_adapt_serial.cpp ../../serialization/build//boost_serialization : : : release ; run test_cpp_dec_float_serial.cpp ../../serialization/build//boost_serialization : : : release TEST1 : test_cpp_dec_float_serial_1 ; run test_cpp_dec_float_serial.cpp ../../serialization/build//boost_serialization : : : release TEST2 : test_cpp_dec_float_serial_2 ; +run test_float128_serial.cpp ../../serialization/build//boost_serialization quadmath : : : release [ check-target-builds ../config//has_float128 : : no ] ; if $(enable-specfun) diff --git a/test/test_adapt_serial.cpp b/test/test_adapt_serial.cpp new file mode 100644 index 00000000..0e3fd87c --- /dev/null +++ b/test/test_adapt_serial.cpp @@ -0,0 +1,136 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 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_ + +// +// Compare arithmetic results using fixed_int to GMP results. +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include +#include +#include "test.hpp" + +#include +#include +#include +#include +#include +#include +#include + +template +T generate_random(unsigned bits_wanted) +{ + static boost::random::mt19937 gen; + typedef boost::random::mt19937::result_type random_type; + + T max_val; + unsigned digits; + if(std::numeric_limits::is_bounded && (bits_wanted == (unsigned)std::numeric_limits::digits)) + { + max_val = (std::numeric_limits::max)(); + digits = std::numeric_limits::digits; + } + else + { + max_val = T(1) << bits_wanted; + digits = bits_wanted; + } + + unsigned bits_per_r_val = std::numeric_limits::digits - 1; + while((random_type(1) << bits_per_r_val) > (gen.max)()) --bits_per_r_val; + + unsigned terms_needed = digits / bits_per_r_val + 1; + + T val = 0; + for(unsigned i = 0; i < terms_needed; ++i) + { + val *= (gen.max)(); + val += gen(); + } + val %= max_val; + return val; +} + +template +void test_neg(const T& x, const boost::mpl::true_&) +{ + T val = -x; + std::stringstream ss; + boost::archive::text_oarchive oa(ss); + oa << static_cast(val); + boost::archive::text_iarchive ia(ss); + T val2; + ia >> val2; + BOOST_CHECK_EQUAL(val, val2); + + ss.clear(); + boost::archive::binary_oarchive ob(ss); + ob << static_cast(val); + boost::archive::binary_iarchive ib(ss); + ib >> val2; + BOOST_CHECK_EQUAL(val, val2); +} +template +void test_neg(const T& , const boost::mpl::false_&){} + +template +void test() +{ + using namespace boost::multiprecision; + + boost::random::mt19937 gen; + boost::uniform_int<> d(3, std::numeric_limits::is_bounded ? std::numeric_limits::digits : 3000); + boost::timer tim; + + while(true) + { + T val = generate_random(d(gen)); + std::stringstream ss; + boost::archive::text_oarchive oa(ss); + oa << static_cast(val); + boost::archive::text_iarchive ia(ss); + T val2; + ia >> val2; + BOOST_CHECK_EQUAL(val, val2); + + ss.clear(); + boost::archive::binary_oarchive ob(ss); + ob << static_cast(val); + boost::archive::binary_iarchive ib(ss); + ib >> val2; + BOOST_CHECK_EQUAL(val, val2); + + test_neg(val, boost::mpl::bool_::is_signed>()); + // + // Check to see if test is taking too long. + // Tests run on the compiler farm time out after 300 seconds, + // so don't get too close to that: + // + if(tim.elapsed() > 30) + { + std::cout << "Timeout reached, aborting tests now....\n"; + break; + } + } +} + +int main() +{ + using namespace boost::multiprecision; + test > > >(); + test > > >(); + return boost::report_errors(); +} + + + diff --git a/test/test_cpp_dec_float_serial.cpp b/test/test_cpp_dec_float_serial.cpp index 1ee773a6..9c6ba295 100644 --- a/test/test_cpp_dec_float_serial.cpp +++ b/test/test_cpp_dec_float_serial.cpp @@ -12,64 +12,7 @@ #endif #include -#include -#include -#include -#include "test.hpp" - -#include -#include -#include -#include -#include - -template -T generate_random(unsigned bits_wanted) -{ - typedef typename T::backend_type::exponent_type e_type; - static boost::random::mt19937 gen; - T val = gen(); - T prev_val = -1; - while(val != prev_val) - { - val *= (gen.max)(); - prev_val = val; - val += gen(); - } - e_type e; - val = frexp(val, &e); - - static boost::random::uniform_int_distribution ui(std::numeric_limits::min_exponent + 1, std::numeric_limits::max_exponent - 1); - return ldexp(val, ui(gen)); -} - -template -void test() -{ - boost::timer tim; - - while(true) - { - T val = generate_random(boost::math::tools::digits()); - std::stringstream ss; - boost::archive::text_oarchive oa(ss); - oa << static_cast(val); - boost::archive::text_iarchive ia(ss); - T val2; - ia >> val2; - BOOST_CHECK_EQUAL(val, val2); - // - // Check to see if test is taking too long. - // Tests run on the compiler farm time out after 300 seconds, - // so don't get too close to that: - // - if(tim.elapsed() > 150) - { - std::cout << "Timeout reached, aborting tests now....\n"; - break; - } - } -} +#include "test_float_serial.hpp" #if !defined(TEST1) && !defined(TEST2) # define TEST1 diff --git a/test/test_float128_serial.cpp b/test/test_float128_serial.cpp new file mode 100644 index 00000000..8966969f --- /dev/null +++ b/test/test_float128_serial.cpp @@ -0,0 +1,26 @@ +/////////////////////////////////////////////////////////////// +// 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_ + +// +// Compare arithmetic results using fixed_int to GMP results. +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include "test_float_serial.hpp" + + +int main() +{ + using namespace boost::multiprecision; + test(); + return boost::report_errors(); +} + + + diff --git a/test/test_float_serial.hpp b/test/test_float_serial.hpp new file mode 100644 index 00000000..da9e0c99 --- /dev/null +++ b/test/test_float_serial.hpp @@ -0,0 +1,91 @@ +/////////////////////////////////////////////////////////////// +// 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_ + +#include +#include +#include +#include "test.hpp" + +#include +#include +#include +#include +#include +#include +#include + + +#ifndef BOOST_MP_TEST_FLOAT_SERIAL_HPP +#define BOOST_MP_TEST_FLOAT_SERIAL_HPP + +template +T generate_random(unsigned bits_wanted) +{ + typedef typename T::backend_type::exponent_type e_type; + static boost::random::mt19937 gen; + T val = gen(); + T prev_val = -1; + while(val != prev_val) + { + val *= (gen.max)(); + prev_val = val; + val += gen(); + } + e_type e; + val = frexp(val, &e); + + static boost::random::uniform_int_distribution ui(std::numeric_limits::min_exponent + 1, std::numeric_limits::max_exponent - 1); + return ldexp(val, ui(gen)); +} + +template +void test() +{ + boost::timer tim; + + while(true) + { + T val = generate_random(boost::math::tools::digits()); + std::stringstream ss; + boost::archive::text_oarchive oa(ss); + oa << static_cast(val); + boost::archive::text_iarchive ia(ss); + T val2; + ia >> val2; + BOOST_CHECK_EQUAL(val, val2); + ss.clear(); + boost::archive::binary_oarchive ba(ss); + ba << static_cast(val); + boost::archive::binary_iarchive ib(ss); + ib >> val2; + BOOST_CHECK_EQUAL(val, val2); + + val = -val; + ss.clear(); + boost::archive::text_oarchive oa2(ss); + oa2 << static_cast(val); + boost::archive::text_iarchive ia2(ss); + ia2 >> val2; + BOOST_CHECK_EQUAL(val, val2); + ss.clear(); + boost::archive::binary_oarchive ba2(ss); + ba2 << static_cast(val); + boost::archive::binary_iarchive ib2(ss); + ib2 >> val2; + BOOST_CHECK_EQUAL(val, val2); + // + // Check to see if test is taking too long. + // Tests run on the compiler farm time out after 300 seconds, + // so don't get too close to that: + // + if(tim.elapsed() > 150) + { + std::cout << "Timeout reached, aborting tests now....\n"; + break; + } + } +} + +#endif \ No newline at end of file