test_int_io.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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_MPZ) && !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT)
  10. #define TEST_TOMMATH
  11. #define TEST_MPZ
  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_MPZ)
  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 "test.hpp"
  33. #include <iostream>
  34. #include <iomanip>
  35. #ifdef BOOST_MSVC
  36. #pragma warning(disable : 4127)
  37. #endif
  38. template <class T>
  39. struct unchecked_type
  40. {
  41. typedef T type;
  42. };
  43. #ifdef TEST_CPP_INT
  44. template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
  45. struct unchecked_type<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >
  46. {
  47. typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, boost::multiprecision::unchecked, Allocator>, ExpressionTemplates> type;
  48. };
  49. #endif
  50. template <class T>
  51. T generate_random()
  52. {
  53. typedef typename unchecked_type<T>::type unchecked_T;
  54. static const unsigned limbs = std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_bounded ? std::numeric_limits<T>::digits / std::numeric_limits<unsigned>::digits + 3 : 20;
  55. static boost::random::uniform_int_distribution<unsigned> ui(0, limbs);
  56. static boost::random::mt19937 gen;
  57. unchecked_T val = gen();
  58. unsigned lim = ui(gen);
  59. for (unsigned i = 0; i < lim; ++i)
  60. {
  61. val *= (gen.max)();
  62. val += gen();
  63. }
  64. return val;
  65. }
  66. template <class T>
  67. void do_round_trip(const T& val, std::ios_base::fmtflags f)
  68. {
  69. std::stringstream ss;
  70. #ifndef BOOST_NO_CXX11_NUMERIC_LIMITS
  71. ss << std::setprecision(std::numeric_limits<T>::max_digits10);
  72. #else
  73. ss << std::setprecision(std::numeric_limits<T>::digits10 + 5);
  74. #endif
  75. ss.flags(f);
  76. ss << val;
  77. T new_val = static_cast<T>(ss.str());
  78. BOOST_CHECK_EQUAL(new_val, val);
  79. new_val = static_cast<T>(val.str(0, f));
  80. BOOST_CHECK_EQUAL(new_val, val);
  81. ss >> new_val;
  82. BOOST_CHECK_EQUAL(new_val, val);
  83. }
  84. template <class T>
  85. void do_round_trip(const T& val)
  86. {
  87. do_round_trip(val, std::ios_base::fmtflags(0));
  88. if (val >= 0)
  89. {
  90. do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase | std::ios_base::hex));
  91. do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase | std::ios_base::oct));
  92. }
  93. }
  94. template <class T>
  95. void negative_round_trip(T val, const boost::mpl::true_&)
  96. {
  97. do_round_trip(T(-val));
  98. }
  99. template <class T>
  100. void negative_round_trip(T, const boost::mpl::false_&)
  101. {
  102. }
  103. template <class T>
  104. void negative_spots(const boost::mpl::true_&)
  105. {
  106. BOOST_CHECK_EQUAL(T(-1002).str(), "-1002");
  107. if (!std::numeric_limits<T>::is_modulo)
  108. {
  109. #ifndef BOOST_NO_EXCEPTIONS
  110. BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::oct), std::runtime_error);
  111. BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::hex), std::runtime_error);
  112. #endif
  113. }
  114. }
  115. template <class T>
  116. void negative_spots(const boost::mpl::false_&)
  117. {
  118. }
  119. template <class T>
  120. void test_round_trip()
  121. {
  122. for (unsigned i = 0; i < 1000; ++i)
  123. {
  124. T val = generate_random<T>();
  125. do_round_trip(val);
  126. negative_round_trip(val, boost::mpl::bool_<std::numeric_limits<T>::is_signed>());
  127. }
  128. BOOST_CHECK_EQUAL(T(1002).str(), "1002");
  129. BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::showpos), "+1002");
  130. BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::oct), "1752");
  131. BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::oct | std::ios_base::showbase), "01752");
  132. BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::hex), "3ea");
  133. BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::hex | std::ios_base::showbase), "0x3ea");
  134. BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::hex | std::ios_base::uppercase), "3EA");
  135. BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::hex | std::ios_base::showbase | std::ios_base::uppercase), "0X3EA");
  136. BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::dec), "1002");
  137. BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::dec | std::ios_base::showbase), "1002");
  138. negative_spots<T>(boost::mpl::bool_<std::numeric_limits<T>::is_signed>());
  139. }
  140. int main()
  141. {
  142. #ifdef TEST_MPZ
  143. test_round_trip<boost::multiprecision::mpz_int>();
  144. #endif
  145. #ifdef TEST_TOMMATH
  146. test_round_trip<boost::multiprecision::tom_int>();
  147. #endif
  148. #ifdef TEST_CPP_INT
  149. test_round_trip<boost::multiprecision::cpp_int>();
  150. test_round_trip<boost::multiprecision::checked_int1024_t>();
  151. test_round_trip<boost::multiprecision::checked_uint512_t>();
  152. test_round_trip<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<32, 32, boost::multiprecision::signed_magnitude, boost::multiprecision::checked, void> > >();
  153. test_round_trip<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<32, 32, boost::multiprecision::unsigned_magnitude, boost::multiprecision::checked, void> > >();
  154. #endif
  155. return boost::report_errors();
  156. }