From ebd7502fdceb08ab4606755d7b0849803c2b660b Mon Sep 17 00:00:00 2001 From: John Maddock Date: Fri, 11 May 2012 17:19:13 +0000 Subject: [PATCH] Enhance pow and powm tests. Quash some warnings. Fix the IO tests on GCC. [SVN r78423] --- include/boost/multiprecision/cpp_int.hpp | 5 ++-- .../detail/generic_interconvert.hpp | 7 +++++ include/boost/multiprecision/integer_ops.hpp | 25 ++++++++++++++++ include/boost/multiprecision/miller_rabin.hpp | 30 ++++++------------- include/boost/multiprecision/mp_number.hpp | 16 +++++----- test/Jamfile.v2 | 3 ++ test/test_arithmetic.cpp | 25 +++++++++++++++- test/test_cpp_int.cpp | 2 +- test/test_float_io.cpp | 29 +++++++++++++++++- 9 files changed, 108 insertions(+), 34 deletions(-) diff --git a/include/boost/multiprecision/cpp_int.hpp b/include/boost/multiprecision/cpp_int.hpp index 1474a6f0..e57e10d6 100644 --- a/include/boost/multiprecision/cpp_int.hpp +++ b/include/boost/multiprecision/cpp_int.hpp @@ -119,14 +119,14 @@ public: { *limbs() = 0; } - cpp_int_base(const cpp_int_base& o) : m_limbs(0), m_internal(true) + cpp_int_base(const cpp_int_base& o) : allocator_type(o), m_limbs(0), m_internal(true) { resize(o.size()); std::memcpy(limbs(), o.limbs(), size() * sizeof(limb_type)); m_sign = o.m_sign; } #ifndef BOOST_NO_RVALUE_REFERENCES - cpp_int_base(cpp_int_base&& o) : m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal) + cpp_int_base(cpp_int_base&& o) : allocator_type(o), m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal) { if(m_internal) { @@ -149,6 +149,7 @@ public: { if(this != &o) { + static_cast(*this) = static_cast(o); m_limbs = 0; resize(o.size()); std::memcpy(limbs(), o.limbs(), size() * sizeof(limb_type)); diff --git a/include/boost/multiprecision/detail/generic_interconvert.hpp b/include/boost/multiprecision/detail/generic_interconvert.hpp index 4356e522..caf83869 100644 --- a/include/boost/multiprecision/detail/generic_interconvert.hpp +++ b/include/boost/multiprecision/detail/generic_interconvert.hpp @@ -107,6 +107,10 @@ void generic_interconvert(To& to, const From& from, const mpl::int_ void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/) { +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif // // The code here only works when the radix of "From" is 2, we could try shifting by other // radixes but it would complicate things.... use a string convertion when the radix is other @@ -178,6 +182,9 @@ void generic_interconvert(To& to, const From& from, const mpl::int_(e)); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif } template diff --git a/include/boost/multiprecision/integer_ops.hpp b/include/boost/multiprecision/integer_ops.hpp index fa4f6976..ccdbbe8b 100644 --- a/include/boost/multiprecision/integer_ops.hpp +++ b/include/boost/multiprecision/integer_ops.hpp @@ -160,7 +160,14 @@ namespace detail{ template void eval_powm(Backend& result, const Backend& a, const Backend& p, const Backend& c) { + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_multiply; + using default_ops::eval_modulus; + using default_ops::eval_right_shift; + typedef typename canonical::type ui_type; + Backend x, y(a), b(p); x = ui_type(1u); while(eval_get_sign(b) > 0) @@ -183,6 +190,12 @@ void eval_powm(Backend& result, const Backend& a, const Backend& p, Integer c) typedef typename canonical::type ui_type; typedef typename canonical::type i_type; + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_multiply; + using default_ops::eval_modulus; + using default_ops::eval_right_shift; + if(eval_get_sign(p) < 0) { BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); @@ -210,6 +223,12 @@ void eval_powm(Backend& result, const Backend& a, Integer b, const Backend& c) typedef typename canonical::type ui_type; typedef typename canonical::type i_type; + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_multiply; + using default_ops::eval_modulus; + using default_ops::eval_right_shift; + if(b < 0) { BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); @@ -238,6 +257,12 @@ void eval_powm(Backend& result, const Backend& a, Integer1 b, Integer2 c) typedef typename canonical::type i1_type; typedef typename canonical::type i2_type; + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_multiply; + using default_ops::eval_modulus; + using default_ops::eval_right_shift; + if(b < 0) { BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); diff --git a/include/boost/multiprecision/miller_rabin.hpp b/include/boost/multiprecision/miller_rabin.hpp index 03f21b53..557114cd 100644 --- a/include/boost/multiprecision/miller_rabin.hpp +++ b/include/boost/multiprecision/miller_rabin.hpp @@ -10,25 +10,6 @@ namespace boost{ namespace multiprecision{ -// -// Calculate (a^b)%c: -// -template -void expmod(const mp_number& a, mp_number b, const mp_number& c, mp_number& result) -{ - typedef mp_number number_type; - number_type x(1), y(a); - while(b > 0) - { - if(b & 1) - { - x = (x * y) % c; - } - y = (y * y) % c; - b /= 2; - } - result = x % c; -} template bool check_small_factors(const mp_number& n) @@ -140,6 +121,10 @@ template typename enable_if_c::value == number_kind_integer, bool>::type miller_rabin_test(const mp_number& n, unsigned trials, Engine& gen) { +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif typedef mp_number number_type; if(n <= 227) @@ -155,7 +140,7 @@ typename enable_if_c::value == number_kind_integer, boo // Begin with a single Fermat test - it excludes a lot of candidates: // number_type q(228), x, y; // We know n is greater than this, as we've excluded small factors - expmod(q, nm1, n, x); + x = powm(q, nm1, n); if(x != 1u) return false; @@ -174,7 +159,7 @@ typename enable_if_c::value == number_kind_integer, boo for(unsigned i = 0; i < trials; ++i) { x = dist(gen); - expmod(x, q, n, y); + y = powm(x, q, n); unsigned j = 0; while(true) { @@ -188,6 +173,9 @@ typename enable_if_c::value == number_kind_integer, boo } } return true; // Yeheh! probably prime. +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif } template diff --git a/include/boost/multiprecision/mp_number.hpp b/include/boost/multiprecision/mp_number.hpp index c75af312..84a5feae 100644 --- a/include/boost/multiprecision/mp_number.hpp +++ b/include/boost/multiprecision/mp_number.hpp @@ -59,12 +59,12 @@ public: mp_number(const mp_number& val) : m_backend(val.m_backend) {} template - mp_number(const mp_number& val, typename enable_if >::type* dummy1 = 0) + mp_number(const mp_number& val, typename enable_if >::type* = 0) { m_backend = val.backend(); } template - mp_number(const mp_number& val, typename disable_if >::type* dummy1 = 0) + mp_number(const mp_number& val, typename disable_if >::type* = 0) { // // Attempt a generic interconvertion: @@ -72,13 +72,13 @@ public: detail::generic_interconvert(backend(), val.backend(), number_category(), number_category()); } template - mp_number(V v1, V v2, typename enable_if, is_same, is_convertible > >::type* dummy1 = 0) + mp_number(V v1, V v2, typename enable_if, is_same, is_convertible > >::type* = 0) { using default_ops::assign_components; assign_components(m_backend, canonical_value(v1), canonical_value(v2)); } template - mp_number(const mp_number& v1, const mp_number& v2, typename enable_if >::type* dummy1 = 0) + mp_number(const mp_number& v1, const mp_number& v2, typename enable_if >::type* = 0) { using default_ops::assign_components; assign_components(m_backend, v1.backend(), v2.backend()); @@ -1136,7 +1136,7 @@ private: do_assign_function_3c(f, val1, val2, val3, t3); } template - void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag2& t2, const Tag3& t3) + void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag2& /*t2*/, const Tag3& t3) { mp_number t(val2); do_assign_function_3c(f, val1, t, val3, t3); @@ -1147,7 +1147,7 @@ private: f(m_backend, function_arg_value(val1), function_arg_value(val2), function_arg_value(val3)); } template - void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag3& t3) + void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag3& /*t3*/) { mp_number t(val3); do_assign_function_3c(f, val1, val2, t, detail::terminal()); @@ -1727,7 +1727,7 @@ inline std::istream& operator >> (std::istream& is, rational= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')))) + while((EOF != (c = static_cast(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')))) { if(c == 'x' || c == 'X') have_hex = true; @@ -1739,7 +1739,7 @@ inline std::istream& operator >> (std::istream& is, rational= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')))) + while((EOF != (c = static_cast(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')))) { if(c == 'x' || c == 'X') have_hex = true; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 006df7b0..31c52fc0 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -23,6 +23,9 @@ project : requirements $(mpfr_path)/build.vc10/lib/Win32/Debug $(tommath_path) msvc:static + msvc:all + gcc:-Wall + gcc:-Wextra ; local enable-specfun = [ MATCH (--enable-specfun) : [ modules.peek : ARGV ] ] ; diff --git a/test/test_arithmetic.cpp b/test/test_arithmetic.cpp index c230a9cd..00b70f4f 100644 --- a/test/test_arithmetic.cpp +++ b/test/test_arithmetic.cpp @@ -412,7 +412,7 @@ void test_integer_ops(const boost::mpl::int_::is_specialized && (!std::numeric_limits::is_bounded || (i * 17 < std::numeric_limits::digits))) + if(std::numeric_limits::is_specialized && (!std::numeric_limits::is_bounded || ((int)i * 17 < std::numeric_limits::digits))) { BOOST_TEST(lsb(Real(1) << (i * 17)) == i * 17); BOOST_TEST(bit_test(Real(1) << (i * 17), i * 17)); @@ -428,6 +428,29 @@ void test_integer_ops(const boost::mpl::int_ diff --git a/test/test_cpp_int.cpp b/test/test_cpp_int.cpp index aba0d58a..52b4102a 100644 --- a/test/test_cpp_int.cpp +++ b/test/test_cpp_int.cpp @@ -284,7 +284,7 @@ void test() BOOST_CHECK_EQUAL(mpz_int(powm(a, ui, c)).str(), test_type(powm(a, ui, c)).str()); } - if(last_error_count != boost::detail::test_errors()) + if(last_error_count != (unsigned)boost::detail::test_errors()) { last_error_count = boost::detail::test_errors(); std::cout << std::hex << std::showbase; diff --git a/test/test_float_io.cpp b/test/test_float_io.cpp index 17bc33d5..fb51eede 100644 --- a/test/test_float_io.cpp +++ b/test/test_float_io.cpp @@ -208,6 +208,33 @@ T generate_random() return ldexp(val, ui(gen)); } +template +struct max_digits10_proxy +{ + static const unsigned value = std::numeric_limits::digits10 + 5; +}; +#ifdef TEST_CPP_DEC_FLOAT +template +struct max_digits10_proxy, ET> > +{ + static const unsigned value = std::numeric_limits, ET> >::max_digits10; +}; +#endif +#ifdef TEST_MPF_50 +template +struct max_digits10_proxy, ET> > +{ + static const unsigned value = std::numeric_limits, ET> >::max_digits10; +}; +#endif +#ifdef TEST_MPFR_50 +template +struct max_digits10_proxy, ET> > +{ + static const unsigned value = std::numeric_limits, ET> >::max_digits10; +}; +#endif + template void do_round_trip(const T& val, std::ios_base::fmtflags f) { @@ -215,7 +242,7 @@ void do_round_trip(const T& val, std::ios_base::fmtflags f) #ifndef BOOST_NO_NUMERIC_LIMITS_LOWEST ss << std::setprecision(std::numeric_limits::max_digits10); #else - ss << std::setprecision(std::numeric_limits::digits10 + 5); + ss << std::setprecision(max_digits10_proxy::value); #endif ss.flags(f); ss << val;