1 ///////////////////////////////////////////////////////////////
2 // Copyright 2013 John Maddock. Distributed under the Boost
3 // Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
5
6 #include <boost/random/mersenne_twister.hpp>
7 #include <boost/random/uniform_int.hpp>
8 #include <boost/timer.hpp>
9 #include "test.hpp"
10
11 #include <iostream>
12 #include <iomanip>
13 #include <sstream>
14 #include <boost/archive/text_iarchive.hpp>
15 #include <boost/archive/text_oarchive.hpp>
16 #include <boost/archive/binary_iarchive.hpp>
17 #include <boost/archive/binary_oarchive.hpp>
18 #include <boost/archive/xml_iarchive.hpp>
19 #include <boost/archive/xml_oarchive.hpp>
20 #include <boost/exception/all.hpp>
21
22 #ifndef BOOST_MP_TEST_FLOAT_SERIAL_HPP
23 #define BOOST_MP_TEST_FLOAT_SERIAL_HPP
24
25 template <class T>
generate_random(unsigned)26 T generate_random(unsigned /*bits_wanted*/)
27 {
28 typedef typename T::backend_type::exponent_type e_type;
29 static boost::random::mt19937 gen;
30 T val = gen();
31 T prev_val = -1;
32 while (val != prev_val)
33 {
34 val *= (gen.max)();
35 prev_val = val;
36 val += gen();
37 }
38 e_type e;
39 val = frexp(val, &e);
40
41 static boost::random::uniform_int_distribution<e_type> ui(std::numeric_limits<T>::min_exponent + 1, std::numeric_limits<T>::max_exponent - 1);
42 return ldexp(val, ui(gen));
43 }
44
45 template <class T>
test()46 void test()
47 {
48 boost::timer tim;
49
50 while (true)
51 {
52 T val = generate_random<T>(boost::math::tools::digits<T>());
53 int test_id = 0;
54 std::string stream_contents;
55 #ifndef BOOST_NO_EXCEPTIONS
56 try
57 {
58 #endif
59 test_id = 0;
60 {
61 std::stringstream ss(std::ios_base::in | std::ios_base::out | std::ios_base::binary);
62 boost::archive::text_oarchive oa(ss);
63 oa << static_cast<const T&>(val);
64 stream_contents = ss.str();
65 boost::archive::text_iarchive ia(ss);
66 T val2;
67 ia >> val2;
68 BOOST_CHECK_EQUAL(val, val2);
69 }
70 {
71 std::stringstream ss(std::ios_base::in | std::ios_base::out | std::ios_base::binary);
72 {
73 boost::archive::xml_oarchive oa(ss);
74 oa << boost::serialization::make_nvp("value", static_cast<const T&>(val));
75 stream_contents = ss.str();
76 }
77 boost::archive::xml_iarchive ia(ss);
78 T val2;
79 ia >> boost::serialization::make_nvp("value", val2);
80 BOOST_CHECK_EQUAL(val, val2);
81 }
82 {
83 std::stringstream ss(std::ios_base::in | std::ios_base::out | std::ios_base::binary);
84 ++test_id;
85 boost::archive::binary_oarchive ba(ss);
86 ba << static_cast<const T&>(val);
87 stream_contents = ss.str();
88 boost::archive::binary_iarchive ib(ss);
89 T val2;
90 ib >> val2;
91 BOOST_CHECK_EQUAL(val, val2);
92 }
93 {
94 std::stringstream ss(std::ios_base::in | std::ios_base::out | std::ios_base::binary);
95 val = -val;
96 ++test_id;
97 boost::archive::text_oarchive oa2(ss);
98 oa2 << static_cast<const T&>(val);
99 stream_contents = ss.str();
100 boost::archive::text_iarchive ia2(ss);
101 T val2;
102 ia2 >> val2;
103 BOOST_CHECK_EQUAL(val, val2);
104 }
105 {
106 std::stringstream ss(std::ios_base::in | std::ios_base::out | std::ios_base::binary);
107 ++test_id;
108 {
109 boost::archive::xml_oarchive oa2(ss);
110 oa2 << boost::serialization::make_nvp("value", static_cast<const T&>(val));
111 stream_contents = ss.str();
112 }
113 boost::archive::xml_iarchive ia2(ss);
114 T val2;
115 ia2 >> boost::serialization::make_nvp("value", val2);
116 BOOST_CHECK_EQUAL(val, val2);
117 }
118 {
119 std::stringstream ss(std::ios_base::in | std::ios_base::out | std::ios_base::binary);
120 ++test_id;
121 boost::archive::binary_oarchive ba2(ss);
122 ba2 << static_cast<const T&>(val);
123 stream_contents = ss.str();
124 boost::archive::binary_iarchive ib2(ss);
125 T val2;
126 ib2 >> val2;
127 BOOST_CHECK_EQUAL(val, val2);
128 }
129 #ifndef BOOST_NO_EXCEPTIONS
130 }
131 catch (const boost::exception& e)
132 {
133 std::cout << "Caught boost::exception with:\n";
134 std::cout << diagnostic_information(e);
135 std::cout << "Failed test ID = " << test_id << std::endl;
136 std::cout << "Stream contents were: \n"
137 << stream_contents << std::endl;
138 ++boost::detail::test_errors();
139 break;
140 }
141 catch (const std::exception& e)
142 {
143 std::cout << "Caught std::exception with:\n";
144 std::cout << e.what() << std::endl;
145 std::cout << "Failed test ID = " << test_id << std::endl;
146 std::cout << "Stream contents were: \n"
147 << stream_contents << std::endl;
148 ++boost::detail::test_errors();
149 break;
150 }
151 #endif
152 //
153 // Check to see if test is taking too long.
154 // Tests run on the compiler farm time out after 300 seconds,
155 // so don't get too close to that:
156 //
157 #ifndef CI_SUPPRESS_KNOWN_ISSUES
158 if (tim.elapsed() > 150)
159 #else
160 if (tim.elapsed() > 25)
161 #endif
162 {
163 std::cout << "Timeout reached, aborting tests now....\n";
164 break;
165 }
166 }
167 }
168
169 #endif
170