Imported Upstream version 1.57.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 http://www.boost.org/LICENSE_1_
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/exception/all.hpp>
30
31 template <class T>
32 T generate_random(unsigned bits_wanted)
33 {
34    static boost::random::mt19937 gen;
35    typedef boost::random::mt19937::result_type random_type;
36
37    T max_val;
38    unsigned digits;
39    if(std::numeric_limits<T>::is_bounded && (bits_wanted == (unsigned)std::numeric_limits<T>::digits))
40    {
41       max_val = (std::numeric_limits<T>::max)();
42       digits = std::numeric_limits<T>::digits;
43    }
44    else
45    {
46       max_val = T(1) << bits_wanted;
47       digits = bits_wanted;
48    }
49
50    unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1;
51    while((random_type(1) << bits_per_r_val) > (gen.max)()) --bits_per_r_val;
52
53    unsigned terms_needed = digits / bits_per_r_val + 1;
54
55    T val = 0;
56    for(unsigned i = 0; i < terms_needed; ++i)
57    {
58       val *= (gen.max)();
59       val += gen();
60    }
61    val %= max_val;
62    return val;
63 }
64
65 template <class T>
66 void test_neg(const T& x, const boost::mpl::true_&)
67 {
68    T val = -x;
69    try
70    {
71       std::stringstream ss;
72       boost::archive::text_oarchive oa(ss);
73       oa << static_cast<const T&>(val);
74       boost::archive::text_iarchive ia(ss);
75       T val2;
76       ia >> val2;
77       BOOST_CHECK_EQUAL(val, val2);
78
79       ss.clear();
80       boost::archive::binary_oarchive ob(ss);
81       ob << static_cast<const T&>(val);
82       boost::archive::binary_iarchive ib(ss);
83       ib >> val2;
84       BOOST_CHECK_EQUAL(val, val2);
85    }
86    catch(const boost::exception& e)
87    {
88       std::cout << "Caught boost::exception with:\n";
89       std::cout << diagnostic_information(e);
90    }
91    catch(const std::exception& e)
92    {
93       std::cout << "Caught std::exception with:\n";
94       std::cout << e.what() << std::endl;
95    }
96 }
97 template <class T>
98 void test_neg(const T& , const boost::mpl::false_&){}
99
100 template <class T>
101 void test()
102 {
103    using namespace boost::multiprecision;
104
105    boost::random::mt19937 gen;
106    boost::uniform_int<> d(3, std::numeric_limits<T>::is_bounded ? std::numeric_limits<T>::digits : 3000);
107    boost::timer tim;
108
109    while(true)
110    {
111       T val = generate_random<T>(d(gen));
112       try
113       {
114          std::stringstream ss;
115          boost::archive::text_oarchive oa(ss);
116          oa << static_cast<const T&>(val);
117          boost::archive::text_iarchive ia(ss);
118          T val2;
119          ia >> val2;
120          BOOST_CHECK_EQUAL(val, val2);
121
122          ss.clear();
123          boost::archive::binary_oarchive ob(ss);
124          ob << static_cast<const T&>(val);
125          boost::archive::binary_iarchive ib(ss);
126          ib >> val2;
127          BOOST_CHECK_EQUAL(val, val2);
128       }
129       catch(const boost::exception& e)
130       {
131          std::cout << "Caught boost::exception with:\n";
132          std::cout << diagnostic_information(e);
133       }
134       catch(const std::exception& e)
135       {
136          std::cout << "Caught std::exception with:\n";
137          std::cout << e.what() << std::endl;
138       }
139       
140       test_neg(val, boost::mpl::bool_<std::numeric_limits<T>::is_signed>());
141       //
142       // Check to see if test is taking too long.
143       // Tests run on the compiler farm time out after 300 seconds,
144       // so don't get too close to that:
145       //
146       if(tim.elapsed() > 30)
147       {
148          std::cout << "Timeout reached, aborting tests now....\n";
149          break;
150       }
151    }
152 }
153
154 int main()
155 {
156    using namespace boost::multiprecision;
157    test<number<logged_adaptor<cpp_int_backend<> > > >();
158    test<number<debug_adaptor<cpp_int_backend<> > > >();
159    return boost::report_errors();
160 }
161
162
163