Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / multiprecision / test / test_adapt_serial.cpp
1 ///////////////////////////////////////////////////////////////
2 //  Copyright 2012 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 //
7 // Compare arithmetic results using fixed_int to GMP results.
8 //
9
10 #ifdef _MSC_VER
11 #define _SCL_SECURE_NO_WARNINGS
12 #endif
13
14 #include <boost/multiprecision/cpp_int.hpp>
15 #include <boost/multiprecision/logged_adaptor.hpp>
16 #include <boost/multiprecision/debug_adaptor.hpp>
17 #include <boost/random/mersenne_twister.hpp>
18 #include <boost/random/uniform_int.hpp>
19 #include <boost/timer.hpp>
20 #include "test.hpp"
21
22 #include <iostream>
23 #include <iomanip>
24 #include <sstream>
25 #include <boost/archive/text_iarchive.hpp>
26 #include <boost/archive/text_oarchive.hpp>
27 #include <boost/archive/binary_iarchive.hpp>
28 #include <boost/archive/binary_oarchive.hpp>
29 #include <boost/archive/xml_iarchive.hpp>
30 #include <boost/archive/xml_oarchive.hpp>
31 #include <boost/exception/all.hpp>
32
33 template <class T>
34 T generate_random(unsigned bits_wanted)
35 {
36    static boost::random::mt19937               gen;
37    typedef boost::random::mt19937::result_type random_type;
38
39    T        max_val;
40    unsigned digits;
41    if (std::numeric_limits<T>::is_bounded && (bits_wanted == (unsigned)std::numeric_limits<T>::digits))
42    {
43       max_val = (std::numeric_limits<T>::max)();
44       digits  = std::numeric_limits<T>::digits;
45    }
46    else
47    {
48       max_val = T(1) << bits_wanted;
49       digits  = bits_wanted;
50    }
51
52    unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1;
53    while ((random_type(1) << bits_per_r_val) > (gen.max)())
54       --bits_per_r_val;
55
56    unsigned terms_needed = digits / bits_per_r_val + 1;
57
58    T val = 0;
59    for (unsigned i = 0; i < terms_needed; ++i)
60    {
61       val *= (gen.max)();
62       val += gen();
63    }
64    val %= max_val;
65    return val;
66 }
67
68 template <class T>
69 void test_neg(const T& x, const boost::mpl::true_&)
70 {
71    T val = -x;
72 #ifndef BOOST_NO_EXCEPTIONS
73    try
74    {
75 #endif
76       T val2;
77       {
78          std::stringstream             ss;
79          boost::archive::text_oarchive oa(ss);
80          oa << static_cast<const T&>(val);
81          boost::archive::text_iarchive ia(ss);
82          ia >> val2;
83          BOOST_CHECK_EQUAL(val, val2);
84       }
85       {
86          std::stringstream ss;
87          {
88             boost::archive::xml_oarchive oa(ss);
89             oa << boost::serialization::make_nvp("value", static_cast<const T&>(val));
90          }
91          boost::archive::xml_iarchive ia(ss);
92          ia >> boost::serialization::make_nvp("value", val2);
93          BOOST_CHECK_EQUAL(val, val2);
94       }
95       {
96          std::stringstream               ss;
97          boost::archive::binary_oarchive ob(ss);
98          ob << static_cast<const T&>(val);
99          boost::archive::binary_iarchive ib(ss);
100          ib >> val2;
101          BOOST_CHECK_EQUAL(val, val2);
102       }
103 #ifndef BOOST_NO_EXCEPTIONS
104    }
105    catch (const boost::exception& e)
106    {
107       std::cout << "Caught boost::exception with:\n";
108       std::cout << diagnostic_information(e);
109    }
110    catch (const std::exception& e)
111    {
112       std::cout << "Caught std::exception with:\n";
113       std::cout << e.what() << std::endl;
114    }
115 #endif
116 }
117 template <class T>
118 void test_neg(const T&, const boost::mpl::false_&) {}
119
120 template <class T>
121 void test()
122 {
123    using namespace boost::multiprecision;
124
125    boost::random::mt19937 gen;
126    boost::uniform_int<>   d(3, std::numeric_limits<T>::is_bounded ? std::numeric_limits<T>::digits : 3000);
127    boost::timer           tim;
128
129    while (true)
130    {
131       T val = generate_random<T>(d(gen));
132 #ifndef BOOST_NO_EXCEPTIONS
133       try
134       {
135 #endif
136          T val2;
137          {
138             std::stringstream             ss;
139             boost::archive::text_oarchive oa(ss);
140             oa << static_cast<const T&>(val);
141             boost::archive::text_iarchive ia(ss);
142             ia >> val2;
143             BOOST_CHECK_EQUAL(val, val2);
144          }
145          {
146             std::stringstream ss;
147             {
148                boost::archive::xml_oarchive oa(ss);
149                oa << boost::serialization::make_nvp("value", static_cast<const T&>(val));
150             }
151             boost::archive::xml_iarchive ia(ss);
152             ia >> boost::serialization::make_nvp("value", val2);
153             BOOST_CHECK_EQUAL(val, val2);
154          }
155          {
156             std::stringstream               ss;
157             boost::archive::binary_oarchive ob(ss);
158             ob << static_cast<const T&>(val);
159             boost::archive::binary_iarchive ib(ss);
160             ib >> val2;
161             BOOST_CHECK_EQUAL(val, val2);
162          }
163 #ifndef BOOST_NO_EXCEPTIONS
164       }
165       catch (const boost::exception& e)
166       {
167          std::cout << "Caught boost::exception with:\n";
168          std::cout << diagnostic_information(e);
169       }
170       catch (const std::exception& e)
171       {
172          std::cout << "Caught std::exception with:\n";
173          std::cout << e.what() << std::endl;
174       }
175 #endif
176       test_neg(val, boost::mpl::bool_<std::numeric_limits<T>::is_signed>());
177       //
178       // Check to see if test is taking too long.
179       // Tests run on the compiler farm time out after 300 seconds,
180       // so don't get too close to that:
181       //
182 #ifndef CI_SUPPRESS_KNOWN_ISSUES
183       if (tim.elapsed() > 30)
184 #else
185       if (tim.elapsed() > 10)
186 #endif
187       {
188          std::cout << "Timeout reached, aborting tests now....\n";
189          break;
190       }
191    }
192 }
193
194 int main()
195 {
196    using namespace boost::multiprecision;
197    test<number<logged_adaptor<cpp_int_backend<> > > >();
198    test<number<debug_adaptor<cpp_int_backend<> > > >();
199    return boost::report_errors();
200 }