Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / multiprecision / test / test_generic_conv.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 #ifdef _MSC_VER
8 #define _SCL_SECURE_NO_WARNINGS
9 #endif
10
11 #include <boost/detail/lightweight_test.hpp>
12 #include <boost/array.hpp>
13 #include "test.hpp"
14
15 #include <boost/multiprecision/cpp_bin_float.hpp>
16 #include <boost/multiprecision/cpp_dec_float.hpp>
17 #include <boost/multiprecision/cpp_int.hpp>
18 #include <boost/random.hpp>
19
20 #ifdef TEST_GMP
21 #include <boost/multiprecision/gmp.hpp>
22 #endif
23 #ifdef TEST_TOMMATH
24 #include <boost/multiprecision/tommath.hpp>
25 #endif
26 #ifdef TEST_MPFR
27 #include <boost/multiprecision/mpfr.hpp>
28 #endif
29
30 int main()
31 {
32    using namespace boost::multiprecision;
33    using namespace boost::random;
34
35    independent_bits_engine<mt11213b, 1024, cpp_int> gen;
36    mt11213b                                         small_gen;
37
38    for (unsigned i = 0; i < 100; ++i)
39    {
40       cpp_int c = gen();
41       //
42       // Integer to integer conversions first:
43       //
44 #ifdef TEST_GMP
45       mpz_int z(c);
46       cpp_int t(z);
47       BOOST_CHECK_EQUAL(t, c);
48       z.assign(-c);
49       t.assign(-z);
50       BOOST_CHECK_EQUAL(t, c);
51 #endif
52 #ifdef TEST_TOMMATH
53       tom_int tom(c);
54       cpp_int t2(tom);
55       BOOST_CHECK_EQUAL(t2, c);
56       tom.assign(-c);
57       t2.assign(-tom);
58       BOOST_CHECK_EQUAL(t2, c);
59 #endif
60       //
61       // Now integer to float:
62       //
63       typedef number<cpp_dec_float<500> > dec_float_500;
64       dec_float_500                       df(c);
65       dec_float_500                       df2(c.str());
66       BOOST_CHECK_EQUAL(df, df2);
67       df.assign(-c);
68       df2 = -df2;
69       BOOST_CHECK_EQUAL(df, df2);
70 #ifdef TEST_GMP
71       typedef number<gmp_float<500> > mpf_type;
72       mpf_type                        mpf(c);
73       mpf_type                        mpf2(c.str());
74       BOOST_CHECK_EQUAL(mpf, mpf2);
75       mpf.assign(-c);
76       mpf2 = -mpf2;
77       BOOST_CHECK_EQUAL(mpf, mpf2);
78 #endif
79 #ifdef TEST_MPFR
80       typedef number<mpfr_float_backend<500> > mpfr_type;
81       mpfr_type                                mpfr(c);
82       mpfr_type                                mpfr2(c.str());
83       BOOST_CHECK_EQUAL(mpfr, mpfr2);
84       mpfr.assign(-c);
85       mpfr2 = -mpfr2;
86       BOOST_CHECK_EQUAL(mpfr, mpfr2);
87 #endif
88       //
89       // Now float to float:
90       //
91       df.assign(c);
92       df /= dec_float_500(gen());
93       dec_float_500 tol("1e-500");
94 #ifdef TEST_GMP
95       mpf.assign(df);
96       mpf2 = static_cast<mpf_type>(df.str());
97       BOOST_CHECK_EQUAL(mpf, mpf2);
98       df.assign(mpf);
99       df2 = static_cast<dec_float_500>(mpf.str());
100       BOOST_CHECK(fabs((df - df2) / df) < tol);
101 #endif
102 #ifdef TEST_MPFR
103       mpfr.assign(df);
104       mpfr2 = static_cast<mpfr_type>(df.str());
105       BOOST_CHECK_EQUAL(mpfr, mpfr2);
106       df.assign(mpfr);
107       df2 = static_cast<dec_float_500>(mpfr.str());
108       BOOST_CHECK(fabs((df - df2) / df) < tol);
109 #endif
110       //
111       // Rational to rational conversions:
112       //
113       cpp_rational cppr(c, gen()), cppr2, cppr3;
114 #ifdef TEST_GMP
115       mpq_rational mpq(cppr);
116       cppr2.assign(mpq);
117       BOOST_CHECK_EQUAL(cppr, cppr2);
118 #endif
119 #ifdef TEST_TOMMATH
120       tom_rational tr(cppr);
121       cppr3.assign(tr);
122       BOOST_CHECK_EQUAL(cppr, cppr3);
123 #endif
124       //
125       // Integer to rational conversions:
126       //
127 #ifdef TEST_GMP
128       mpq.assign(c);
129       mpq_rational mpq2 = static_cast<mpq_rational>(c.str());
130       BOOST_CHECK_EQUAL(mpq, mpq2);
131 #endif
132 #ifdef TEST_TOMMATH
133       tr.assign(c);
134       tom_rational tr2 = static_cast<tom_rational>(c.str());
135       BOOST_CHECK_EQUAL(tr, tr2);
136 #endif
137       //
138       // Rational to float:
139       //
140       df.assign(cppr);
141       df2.assign(numerator(cppr));
142       df2 /= dec_float_500(denominator(cppr));
143       BOOST_CHECK(fabs(df - df2) / df2 < tol);
144       //
145       // Float to rational:
146       //
147       static const int                                       max_range = std::numeric_limits<double>::digits >= std::numeric_limits<int>::digits ? (std::numeric_limits<int>::max)() : (1 << (std::numeric_limits<double>::digits - 1)) - 1;
148       static const int                                       min_range = std::numeric_limits<double>::digits >= std::numeric_limits<int>::digits ? (std::numeric_limits<int>::min)() : -(1 << (std::numeric_limits<double>::digits - 1)) + 1;
149       static const boost::random::uniform_int_distribution<> i_val_dist(min_range, max_range);
150       static const boost::random::uniform_int_distribution<> i_exp_dist(std::numeric_limits<double>::min_exponent, std::numeric_limits<double>::max_exponent - 2 - std::numeric_limits<int>::digits);
151       int                                                    iv   = i_val_dist(small_gen);
152       int                                                    eval = i_exp_dist(small_gen);
153       double                                                 dv   = iv;
154       dv                                                          = ldexp(dv, eval);
155       cppr                                                        = dv;
156       cppr2                                                       = iv;
157       cpp_int cppi                                                = 1;
158       cppi <<= abs(eval);
159       if (eval < 0)
160          cppr2 /= cppi;
161       else
162          cppr2 *= cppi;
163       BOOST_CHECK_EQUAL(cppr, cppr2);
164       //
165       // Again but with bigger numbers:
166       //
167       cpp_int                      cppi2 = gen();
168       number<cpp_bin_float<1030> > cppbf(cppi2);
169       cppbf = ldexp(cppbf, eval);
170       cppr.assign(cppbf);
171       cppr2 = cppi2;
172       if (eval < 0)
173          cppr2 /= cppi;
174       else
175          cppr2 *= cppi;
176       BOOST_CHECK_EQUAL(cppr, cppr2);
177       //
178       // MSVC will compile either the code above, or
179       // the code below, but not both in the same file.
180       // Other compilers including Intel in msvc-compatibity
181       // mode have no such difficulty.  Indeed the fact that
182       // the presence of the code below causes the code above to
183       // fail to compile strongly suggests a compiler bug.
184       //
185 #if !defined(BOOST_MSVC)
186       //
187       // Again but with bigger base 10 numbers:
188       //
189       number<cpp_dec_float<std::numeric_limits<int1024_t>::digits10 + 3> > cppdec2(cppi2);
190       cppdec2 = scalbn(cppdec2, eval);
191       cppr.assign(cppdec2);
192       cppr2 = cppi2;
193       cppi  = 10;
194       cppi  = pow(cppi, abs(eval));
195       if (eval < 0)
196          cppr2 /= cppi;
197       else
198          cppr2 *= cppi;
199       BOOST_CHECK_EQUAL(cppr, cppr2);
200 #endif
201    }
202
203    return boost::report_errors();
204 }