test_rational_io.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright John Maddock 2011.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifdef _MSC_VER
  7. #define _SCL_SECURE_NO_WARNINGS
  8. #endif
  9. #if !defined(TEST_MPQ) && !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT)
  10. #define TEST_MPQ
  11. #define TEST_TOMMATH
  12. #define TEST_CPP_INT
  13. #ifdef _MSC_VER
  14. #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
  15. #endif
  16. #ifdef __GNUC__
  17. #pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!"
  18. #endif
  19. #endif
  20. #if defined(TEST_MPQ)
  21. #include <boost/multiprecision/gmp.hpp>
  22. #endif
  23. #if defined(TEST_TOMMATH)
  24. #include <boost/multiprecision/tommath.hpp>
  25. #endif
  26. #ifdef TEST_CPP_INT
  27. #include <boost/multiprecision/cpp_int.hpp>
  28. #endif
  29. #include <boost/algorithm/string/case_conv.hpp>
  30. #include <boost/random/mersenne_twister.hpp>
  31. #include <boost/random/uniform_int.hpp>
  32. #include <boost/multiprecision/rational_adaptor.hpp>
  33. #include "test.hpp"
  34. #include <iostream>
  35. #include <iomanip>
  36. template <class T>
  37. T generate_random()
  38. {
  39. typedef typename boost::multiprecision::component_type<T>::type int_type;
  40. static boost::random::uniform_int_distribution<unsigned> ui(0, 20);
  41. static boost::random::mt19937 gen;
  42. int_type val = int_type(gen());
  43. unsigned lim = ui(gen);
  44. for (unsigned i = 0; i < lim; ++i)
  45. {
  46. val *= (gen.max)();
  47. val += gen();
  48. }
  49. int_type denom = int_type(gen());
  50. lim = ui(gen);
  51. for (unsigned i = 0; i < lim; ++i)
  52. {
  53. denom *= (gen.max)();
  54. denom += gen();
  55. }
  56. return T(val, denom);
  57. }
  58. template <class T>
  59. void do_round_trip(const T& val, std::ios_base::fmtflags f, const boost::mpl::true_&)
  60. {
  61. std::stringstream ss;
  62. #ifndef BOOST_NO_CXX11_NUMERIC_LIMITS
  63. ss << std::setprecision(std::numeric_limits<T>::max_digits10);
  64. #else
  65. ss << std::setprecision(std::numeric_limits<T>::digits10 + 5);
  66. #endif
  67. ss.flags(f);
  68. ss << val;
  69. T new_val = static_cast<T>(ss.str());
  70. BOOST_CHECK_EQUAL(new_val, val);
  71. new_val = static_cast<T>(val.str(0, f));
  72. BOOST_CHECK_EQUAL(new_val, val);
  73. }
  74. template <class T>
  75. void do_round_trip(const T& val, std::ios_base::fmtflags f, const boost::mpl::false_&)
  76. {
  77. std::stringstream ss;
  78. ss << std::setprecision(std::numeric_limits<T>::digits10 + 4);
  79. ss.flags(f);
  80. ss << val;
  81. T new_val;
  82. ss >> new_val;
  83. BOOST_CHECK_EQUAL(new_val, val);
  84. }
  85. template <class T>
  86. struct is_number : public boost::mpl::false_
  87. {};
  88. template <class T>
  89. struct is_number<boost::multiprecision::number<T> > : public boost::mpl::true_
  90. {};
  91. template <class T>
  92. void do_round_trip(const T& val, std::ios_base::fmtflags f)
  93. {
  94. do_round_trip(val, f, is_number<T>());
  95. }
  96. template <class T>
  97. void do_round_trip(const T& val)
  98. {
  99. do_round_trip(val, std::ios_base::fmtflags(0));
  100. if (val >= 0)
  101. {
  102. do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase | std::ios_base::hex));
  103. do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase | std::ios_base::oct));
  104. }
  105. }
  106. template <class T>
  107. void test_round_trip()
  108. {
  109. for (unsigned i = 0; i < 1000; ++i)
  110. {
  111. T val = generate_random<T>();
  112. do_round_trip(val);
  113. do_round_trip(T(-val));
  114. }
  115. }
  116. int main()
  117. {
  118. #ifdef TEST_MPQ
  119. test_round_trip<boost::multiprecision::mpq_rational>();
  120. test_round_trip<boost::rational<boost::multiprecision::mpz_int> >();
  121. test_round_trip<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::gmp_int> > >();
  122. #endif
  123. #ifdef TEST_TOMMATH
  124. test_round_trip<boost::rational<boost::multiprecision::tom_int> >();
  125. test_round_trip<boost::multiprecision::tom_rational>();
  126. #endif
  127. #ifdef TEST_CPP_INT
  128. test_round_trip<boost::rational<boost::multiprecision::cpp_int> >();
  129. test_round_trip<boost::multiprecision::cpp_rational>();
  130. #endif
  131. return boost::report_errors();
  132. }