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_
7 # define _SCL_SECURE_NO_WARNINGS
10 #include <boost/multiprecision/cpp_int.hpp>
11 #include <boost/random/mersenne_twister.hpp>
15 #include <boost/multiprecision/gmp.hpp>
18 #include <boost/multiprecision/mpfr.hpp>
21 #include <boost/multiprecision/mpfi.hpp>
24 #include <boost/multiprecision/tommath.hpp>
27 #include <boost/multiprecision/float128.hpp>
29 #include <boost/multiprecision/cpp_bin_float.hpp>
30 #include <boost/multiprecision/cpp_dec_float.hpp>
33 using namespace boost::multiprecision
;
36 #pragma warning(disable:4127)
41 T
generate_random_int(unsigned bits_wanted
)
43 static boost::random::mt19937 gen
;
44 typedef boost::random::mt19937::result_type random_type
;
48 if(std::numeric_limits
<T
>::is_bounded
&& (bits_wanted
== (unsigned)std::numeric_limits
<T
>::digits
))
50 max_val
= (std::numeric_limits
<T
>::max
)();
51 digits
= std::numeric_limits
<T
>::digits
;
55 max_val
= T(1) << bits_wanted
;
59 unsigned bits_per_r_val
= std::numeric_limits
<random_type
>::digits
- 1;
60 while((random_type(1) << bits_per_r_val
) > (gen
.max
)()) --bits_per_r_val
;
62 unsigned terms_needed
= digits
/ bits_per_r_val
+ 1;
65 for(unsigned i
= 0; i
< terms_needed
; ++i
)
75 T
generate_random(unsigned bits_wanted
)
77 typedef typename component_type
<T
>::type int_type
;
78 T
val(generate_random_int
<int_type
>(bits_wanted
), generate_random_int
<int_type
>(bits_wanted
));
82 template <class From
, class To
>
83 void test_convert_neg_val(From from
, const boost::mpl::true_
&)
86 typename component_type
<From
>::type answer
= numerator(from
) / denominator(from
);
88 To t4
= from
.template convert_to
<To
>();
89 BOOST_CHECK_EQUAL(answer
.str(), t3
.str());
90 BOOST_CHECK_EQUAL(answer
.str(), t4
.str());
92 template <class From
, class To
>
93 void test_convert_neg_val(From
const&, const boost::mpl::false_
&)
97 template <class From
, class To
>
98 void test_convert_imp(boost::mpl::int_
<number_kind_rational
> const&, boost::mpl::int_
<number_kind_integer
> const&)
100 int bits_wanted
= (std::min
)((std::min
)(std::numeric_limits
<From
>::digits
, std::numeric_limits
<To
>::digits
), 2000);
102 for(unsigned i
= 0; i
< 100; ++i
)
104 From from
= generate_random
<From
>(bits_wanted
);
105 typename component_type
<From
>::type answer
= numerator(from
) / denominator(from
);
107 To t2
= from
.template convert_to
<To
>();
108 BOOST_CHECK_EQUAL(answer
.str(), t1
.str());
109 BOOST_CHECK_EQUAL(answer
.str(), t2
.str());
110 test_convert_neg_val
<From
, To
>(from
, boost::mpl::bool_
<std::numeric_limits
<From
>::is_signed
&& std::numeric_limits
<To
>::is_signed
>());
114 template <class From
, class To
>
115 void test_convert_neg_float_val(From from
, To
const& tol
, const boost::mpl::true_
&)
118 To answer
= To(numerator(from
)) / To(denominator(from
));
120 To t4
= from
.template convert_to
<To
>();
121 BOOST_CHECK_CLOSE_FRACTION(answer
, t3
, tol
);
122 BOOST_CHECK_CLOSE_FRACTION(answer
, t4
, tol
);
124 template <class From
, class To
>
125 void test_convert_neg_float_val(From
const&, To
const&, const boost::mpl::false_
&)
129 template <class From
, class To
>
130 void test_convert_imp(boost::mpl::int_
<number_kind_rational
> const&, boost::mpl::int_
<number_kind_floating_point
> const&)
132 int bits_wanted
= (std::min
)((std::min
)(std::numeric_limits
<From
>::digits
, std::numeric_limits
<To
>::digits
), 2000);
134 for(unsigned i
= 0; i
< 100; ++i
)
136 From from
= generate_random
<From
>(bits_wanted
);
137 To answer
= To(numerator(from
)) / To(denominator(from
));
139 To t2
= from
.template convert_to
<To
>();
140 To tol
= std::numeric_limits
<To
>::is_specialized
? std::numeric_limits
<To
>::epsilon() : ldexp(To(1), 1 - bits_wanted
);
142 BOOST_CHECK_CLOSE_FRACTION(answer
, t1
, tol
);
143 BOOST_CHECK_CLOSE_FRACTION(answer
, t2
, tol
);
144 test_convert_neg_float_val
<From
, To
>(from
, tol
, boost::mpl::bool_
<std::numeric_limits
<From
>::is_signed
&& std::numeric_limits
<To
>::is_signed
>());
148 template <class From
, class To
>
149 void test_convert_neg_rat_val(From from
, const boost::mpl::true_
&)
153 To t4
= from
.template convert_to
<To
>();
154 BOOST_CHECK_EQUAL(from
.str(), t3
.str());
155 BOOST_CHECK_EQUAL(from
.str(), t4
.str());
157 template <class From
, class To
>
158 void test_convert_neg_rat_val(From
const&, const boost::mpl::false_
&)
162 template <class From
, class To
>
163 void test_convert_imp(boost::mpl::int_
<number_kind_rational
> const&, boost::mpl::int_
<number_kind_rational
> const&)
165 int bits_wanted
= (std::min
)((std::min
)(std::numeric_limits
<From
>::digits
, std::numeric_limits
<To
>::digits
), 2000);
167 for(unsigned i
= 0; i
< 100; ++i
)
169 From from
= generate_random
<From
>(bits_wanted
);
171 To t2
= from
.template convert_to
<To
>();
172 BOOST_CHECK_EQUAL(from
.str(), t1
.str());
173 BOOST_CHECK_EQUAL(from
.str(), t2
.str());
174 test_convert_neg_rat_val
<From
, To
>(from
, boost::mpl::bool_
<std::numeric_limits
<From
>::is_signed
&& std::numeric_limits
<To
>::is_signed
>());
181 template <class From
, class To
>
184 test_convert_imp
<From
, To
>(typename number_category
<From
>::type(), typename number_category
<To
>::type());
190 test_convert
<cpp_rational
, cpp_int
>();
191 test_convert
<cpp_rational
, int128_t
>();
192 test_convert
<cpp_rational
, uint128_t
>();
194 test_convert
<cpp_rational
, cpp_bin_float_50
>();
196 test_convert
<cpp_rational
, cpp_dec_float_50
>();
199 test_convert
<cpp_rational
, mpz_int
>();
200 test_convert
<cpp_rational
, mpq_rational
>();
201 test_convert
<cpp_rational
, mpf_float_50
>();
203 #if defined(HAS_MPFR)
204 test_convert
<cpp_rational
, mpfr_float_50
>();
206 #if defined(HAS_MPFI)
207 test_convert
<cpp_rational
, mpfi_float_50
>();
210 test_convert
<cpp_rational
, tom_int
>();
211 test_convert
<cpp_rational
, tom_rational
>();
213 return boost::report_errors();