diff --git a/include/boost/integer/common_factor_rt.hpp b/include/boost/integer/common_factor_rt.hpp index d79a9c5..65f18d2 100644 --- a/include/boost/integer/common_factor_rt.hpp +++ b/include/boost/integer/common_factor_rt.hpp @@ -83,9 +83,9 @@ namespace boost { } #endif - template ::value || + std::is_unsigned::value || #endif (std::numeric_limits::is_specialized && !std::numeric_limits::is_signed)> struct gcd_traits_abs_defaults @@ -210,28 +210,28 @@ namespace boost { // this works for signed types too, as by the time these functions // are called, all values are > 0. // - template <> struct gcd_traits : public gcd_traits_defaults + template <> struct gcd_traits : public gcd_traits_defaults { BOOST_FORCEINLINE static unsigned make_odd(long& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits::find_lsb(val); val >>= result; return result; } }; - template <> struct gcd_traits : public gcd_traits_defaults + template <> struct gcd_traits : public gcd_traits_defaults { BOOST_FORCEINLINE static unsigned make_odd(unsigned int& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits::find_lsb(val); val >>= result; return result; } }; - template <> struct gcd_traits : public gcd_traits_defaults + template <> struct gcd_traits : public gcd_traits_defaults { BOOST_FORCEINLINE static unsigned make_odd(int& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits::find_lsb(val); val >>= result; return result; } }; - template <> struct gcd_traits : public gcd_traits_defaults + template <> struct gcd_traits : public gcd_traits_defaults { BOOST_FORCEINLINE static unsigned make_odd(unsigned short& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits::find_lsb(val); val >>= result; return result; } }; - template <> struct gcd_traits : public gcd_traits_defaults + template <> struct gcd_traits : public gcd_traits_defaults { BOOST_FORCEINLINE static unsigned make_odd(short& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits::find_lsb(val); val >>= result; return result; } }; - template <> struct gcd_traits : public gcd_traits_defaults + template <> struct gcd_traits : public gcd_traits_defaults { BOOST_FORCEINLINE static unsigned make_odd(unsigned char& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits::find_lsb(val); val >>= result; return result; } }; - template <> struct gcd_traits : public gcd_traits_defaults + template <> struct gcd_traits : public gcd_traits_defaults { BOOST_FORCEINLINE static unsigned make_odd(signed char& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits::find_lsb(val); val >>= result; return result; } }; - template <> struct gcd_traits : public gcd_traits_defaults + template <> struct gcd_traits : public gcd_traits_defaults { BOOST_FORCEINLINE static unsigned make_odd(char& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits::find_lsb(val); val >>= result; return result; } }; #ifndef BOOST_NO_INTRINSIC_WCHAR_T - template <> struct gcd_traits : public gcd_traits_defaults + template <> struct gcd_traits : public gcd_traits_defaults { BOOST_FORCEINLINE static unsigned make_odd(wchar_t& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits::find_lsb(val); val >>= result; return result; } }; #endif #ifdef _M_X64 - template <> struct gcd_traits<__int64> : public gcd_traits_defaults<__int64> + template <> struct gcd_traits<__int64> : public gcd_traits_defaults<__int64> { BOOST_FORCEINLINE static unsigned make_odd(__int64& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits::find_lsb(val); val >>= result; return result; } }; #endif @@ -360,7 +360,7 @@ namespace boost { } /** Stein gcd (aka 'binary gcd') - * + * * From Mathematics to Generic Programming, Alexander Stepanov, Daniel Rose */ template @@ -388,11 +388,11 @@ namespace boost { return m; } - + /** Euclidean algorithm - * + * * From Mathematics to Generic Programming, Alexander Stepanov, Daniel Rose - * + * */ template inline BOOST_CXX14_CONSTEXPR EuclideanDomain Euclid_gcd(EuclideanDomain a, EuclideanDomain b) BOOST_GCD_NOEXCEPT(EuclideanDomain) @@ -494,10 +494,10 @@ inline typename boost::enable_if_c::is_specialized, * * Knuth counts down from n to zero but we naturally go from first to last. * We also return the termination position because it might be useful to know. - * - * Partly by quirk, partly by design, this algorithm is defined for n = 1, + * + * Partly by quirk, partly by design, this algorithm is defined for n = 1, * because the gcd of {x} is x. It is not defined for n = 0. - * + * * @tparam I Input iterator. * @return The gcd of the range and the iterator position at termination. */ @@ -507,12 +507,13 @@ gcd_range(I first, I last) BOOST_GCD_NOEXCEPT(I) { BOOST_ASSERT(first != last); typedef typename std::iterator_traits::value_type T; - - T d = *first++; + + T d = *first; + ++first; while (d != T(1) && first != last) { d = gcd(d, *first); - first++; + ++first; } return std::make_pair(d, first); } @@ -522,12 +523,13 @@ lcm_range(I first, I last) BOOST_GCD_NOEXCEPT(I) { BOOST_ASSERT(first != last); typedef typename std::iterator_traits::value_type T; - - T d = *first++; - while (d != T(1) && first != last) + + T d = *first; + ++first; + while (d != T(0) && first != last) { d = lcm(d, *first); - first++; + ++first; } return std::make_pair(d, first); } @@ -544,7 +546,7 @@ public: typedef IntegerType second_argument_type; typedef IntegerType result_type; #endif - IntegerType operator()(IntegerType const &a, IntegerType const &b)const + IntegerType operator()(IntegerType const &a, IntegerType const &b) const { return boost::integer::gcd(a, b); } diff --git a/test/common_factor_test.cpp b/test/common_factor_test.cpp index 682d55b..0b933b8 100644 --- a/test/common_factor_test.cpp +++ b/test/common_factor_test.cpp @@ -542,6 +542,15 @@ void variadics() BOOST_TEST_EQ(boost::integer::gcd_range(i, i + 4).second, i + 4); BOOST_TEST_EQ(boost::integer::lcm_range(i, i + 4).first, 11704); BOOST_TEST_EQ(boost::integer::lcm_range(i, i + 4).second, i + 4); + + unsigned i_gcd_unity[] = { 44, 56, 1, 88 }; + BOOST_TEST_EQ(boost::integer::gcd_range(i_gcd_unity, i_gcd_unity + 4).first, 1); + BOOST_TEST_EQ(boost::integer::gcd_range(i_gcd_unity, i_gcd_unity + 4).second, i_gcd_unity + 3); + + unsigned i_lcm_unity[] = { 44, 56, 0, 88 }; + BOOST_TEST_EQ(boost::integer::lcm_range(i_lcm_unity, i_lcm_unity + 4).first, 0); + BOOST_TEST_EQ(boost::integer::lcm_range(i_lcm_unity, i_lcm_unity + 4).second, i_lcm_unity + 3); + #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES BOOST_TEST_EQ(boost::integer::gcd(i[0], i[1], i[2], i[3]), 4); BOOST_TEST_EQ(boost::integer::lcm(i[0], i[1], i[2], i[3]), 11704);