test_generic_conv.cpp 6.5 KB

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