test_convert_from_cpp_int.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. #ifdef _MSC_VER
  6. #define _SCL_SECURE_NO_WARNINGS
  7. #endif
  8. #include <boost/multiprecision/cpp_int.hpp>
  9. #include <boost/random/mersenne_twister.hpp>
  10. #include "test.hpp"
  11. #if defined(HAS_GMP)
  12. #include <boost/multiprecision/gmp.hpp>
  13. #endif
  14. #if defined(HAS_MPFR)
  15. #include <boost/multiprecision/mpfr.hpp>
  16. #endif
  17. #if defined(HAS_MPFI)
  18. #include <boost/multiprecision/mpfi.hpp>
  19. #endif
  20. #ifdef HAS_TOMMATH
  21. #include <boost/multiprecision/tommath.hpp>
  22. #endif
  23. #ifdef HAS_FLOAT128
  24. #include <boost/multiprecision/float128.hpp>
  25. #endif
  26. #include <boost/multiprecision/cpp_bin_float.hpp>
  27. #include <boost/multiprecision/cpp_dec_float.hpp>
  28. using namespace boost::multiprecision;
  29. #ifdef BOOST_MSVC
  30. #pragma warning(disable : 4127)
  31. #endif
  32. template <class T>
  33. T generate_random(unsigned bits_wanted)
  34. {
  35. static boost::random::mt19937 gen;
  36. typedef boost::random::mt19937::result_type random_type;
  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. unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1;
  50. while ((random_type(1) << bits_per_r_val) > (gen.max)())
  51. --bits_per_r_val;
  52. unsigned terms_needed = digits / bits_per_r_val + 1;
  53. T val = 0;
  54. for (unsigned i = 0; i < terms_needed; ++i)
  55. {
  56. val *= (gen.max)();
  57. val += gen();
  58. }
  59. val %= max_val;
  60. return val;
  61. }
  62. template <class From, class To>
  63. void test_convert_neg_int(From from, const boost::mpl::true_&)
  64. {
  65. from = -from;
  66. To t3(from);
  67. To t4 = from.template convert_to<To>();
  68. BOOST_CHECK_EQUAL(from.str(), t3.str());
  69. BOOST_CHECK_EQUAL(from.str(), t4.str());
  70. }
  71. template <class From, class To>
  72. void test_convert_neg_int(From const&, const boost::mpl::false_&)
  73. {
  74. }
  75. template <class From, class To>
  76. void test_convert_imp(boost::mpl::int_<number_kind_integer> const&, boost::mpl::int_<number_kind_integer> const&)
  77. {
  78. int bits_wanted = (std::min)((std::min)(std::numeric_limits<From>::digits, std::numeric_limits<To>::digits), 2000);
  79. for (unsigned i = 0; i < 100; ++i)
  80. {
  81. From from = generate_random<From>(bits_wanted);
  82. To t1(from);
  83. To t2 = from.template convert_to<To>();
  84. BOOST_CHECK_EQUAL(from.str(), t1.str());
  85. BOOST_CHECK_EQUAL(from.str(), t2.str());
  86. test_convert_neg_int<From, To>(from, boost::mpl::bool_ < std::numeric_limits<From>::is_signed && std::numeric_limits<To>::is_signed > ());
  87. }
  88. }
  89. template <class From, class To>
  90. void test_convert_neg_rat(From from, const boost::mpl::true_&)
  91. {
  92. from = -from;
  93. To t3(from);
  94. To t4 = from.template convert_to<To>();
  95. BOOST_CHECK_EQUAL(from.str(), numerator(t3).str());
  96. BOOST_CHECK_EQUAL(from.str(), numerator(t4).str());
  97. }
  98. template <class From, class To>
  99. void test_convert_neg_rat(From const&, const boost::mpl::false_&)
  100. {
  101. }
  102. template <class From, class To>
  103. void test_convert_imp(boost::mpl::int_<number_kind_integer> const&, boost::mpl::int_<number_kind_rational> const&)
  104. {
  105. int bits_wanted = (std::min)((std::min)(std::numeric_limits<From>::digits, std::numeric_limits<To>::digits), 2000);
  106. for (unsigned i = 0; i < 100; ++i)
  107. {
  108. From from = generate_random<From>(bits_wanted);
  109. To t1(from);
  110. To t2 = from.template convert_to<To>();
  111. BOOST_CHECK_EQUAL(from.str(), numerator(t1).str());
  112. BOOST_CHECK_EQUAL(from.str(), numerator(t2).str());
  113. test_convert_neg_rat<From, To>(from, boost::mpl::bool_ < std::numeric_limits<From>::is_signed && std::numeric_limits<To>::is_signed > ());
  114. }
  115. }
  116. template <class From, class To>
  117. void test_convert_neg_float(From from, const boost::mpl::true_&)
  118. {
  119. from = -from;
  120. To t3(from);
  121. To t4 = from.template convert_to<To>();
  122. To check(from.str() + ".0");
  123. BOOST_CHECK_EQUAL(t3, check);
  124. BOOST_CHECK_EQUAL(t4, check);
  125. }
  126. template <class From, class To>
  127. void test_convert_neg_float(From const&, const boost::mpl::false_&)
  128. {
  129. }
  130. template <class From, class To>
  131. void test_convert_imp(boost::mpl::int_<number_kind_integer> const&, boost::mpl::int_<number_kind_floating_point> const&)
  132. {
  133. 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)
  135. {
  136. From from = generate_random<From>(bits_wanted);
  137. To t1(from);
  138. To t2 = from.template convert_to<To>();
  139. To check(from.str() + ".0");
  140. BOOST_CHECK_EQUAL(t1, check);
  141. BOOST_CHECK_EQUAL(t2, check);
  142. test_convert_neg_float<From, To>(from, boost::mpl::bool_ < std::numeric_limits<From>::is_signed && std::numeric_limits<To>::is_signed > ());
  143. }
  144. }
  145. template <class From, class To>
  146. void test_convert()
  147. {
  148. test_convert_imp<From, To>(typename number_category<From>::type(), typename number_category<To>::type());
  149. }
  150. int main()
  151. {
  152. test_convert<cpp_int, int128_t>();
  153. test_convert<int128_t, cpp_int>();
  154. test_convert<cpp_int, cpp_rational>();
  155. test_convert<int128_t, cpp_rational>();
  156. test_convert<uint128_t, cpp_rational>();
  157. test_convert<cpp_int, cpp_bin_float_50>();
  158. test_convert<int128_t, cpp_bin_float_50>();
  159. test_convert<uint128_t, cpp_bin_float_50>();
  160. test_convert<cpp_int, cpp_dec_float_50>();
  161. test_convert<int128_t, cpp_dec_float_50>();
  162. test_convert<uint128_t, cpp_dec_float_50>();
  163. #if defined(HAS_GMP)
  164. test_convert<cpp_int, mpz_int>();
  165. test_convert<int128_t, mpz_int>();
  166. test_convert<uint128_t, mpz_int>();
  167. test_convert<cpp_int, mpq_rational>();
  168. test_convert<int128_t, mpq_rational>();
  169. test_convert<uint128_t, mpq_rational>();
  170. test_convert<cpp_int, mpf_float_50>();
  171. test_convert<int128_t, mpf_float_50>();
  172. test_convert<uint128_t, mpf_float_50>();
  173. #endif
  174. #if defined(HAS_MPFR)
  175. test_convert<cpp_int, mpfr_float_50>();
  176. test_convert<int128_t, mpfr_float_50>();
  177. test_convert<uint128_t, mpfr_float_50>();
  178. #endif
  179. #if defined(HAS_MPFI)
  180. test_convert<cpp_int, mpfi_float_50>();
  181. test_convert<int128_t, mpfi_float_50>();
  182. test_convert<uint128_t, mpfi_float_50>();
  183. #endif
  184. #ifdef HAS_TOMMATH
  185. test_convert<cpp_int, tom_int>();
  186. test_convert<int128_t, tom_int>();
  187. test_convert<uint128_t, tom_int>();
  188. test_convert<cpp_int, tom_rational>();
  189. test_convert<int128_t, tom_rational>();
  190. test_convert<uint128_t, tom_rational>();
  191. #endif
  192. #ifdef HAS_FLOAT128
  193. test_convert<cpp_int, float128>();
  194. test_convert<int128_t, float128>();
  195. test_convert<uint128_t, float128>();
  196. #endif
  197. return boost::report_errors();
  198. }