Fixed incorrect loop termination in lcm_range.

lcm_range used to incorrectly terminate on value of 1. Instead, it should
terminate on 0 since any further elements of the range no longer affect
the result of the function.

Also, added tests for the gcd_range and lcm_range functions verifying
that they terminate their loops at the correct points.
This commit is contained in:
Andrey Semashev
2019-03-26 01:55:18 +03:00
parent 5195d682ec
commit 33c165552c
2 changed files with 38 additions and 27 deletions

View File

@ -508,11 +508,12 @@ gcd_range(I first, I last) BOOST_GCD_NOEXCEPT(I)
BOOST_ASSERT(first != last); BOOST_ASSERT(first != last);
typedef typename std::iterator_traits<I>::value_type T; typedef typename std::iterator_traits<I>::value_type T;
T d = *first++; T d = *first;
++first;
while (d != T(1) && first != last) while (d != T(1) && first != last)
{ {
d = gcd(d, *first); d = gcd(d, *first);
first++; ++first;
} }
return std::make_pair(d, first); return std::make_pair(d, first);
} }
@ -523,11 +524,12 @@ lcm_range(I first, I last) BOOST_GCD_NOEXCEPT(I)
BOOST_ASSERT(first != last); BOOST_ASSERT(first != last);
typedef typename std::iterator_traits<I>::value_type T; typedef typename std::iterator_traits<I>::value_type T;
T d = *first++; T d = *first;
while (d != T(1) && first != last) ++first;
while (d != T(0) && first != last)
{ {
d = lcm(d, *first); d = lcm(d, *first);
first++; ++first;
} }
return std::make_pair(d, first); return std::make_pair(d, first);
} }
@ -544,7 +546,7 @@ public:
typedef IntegerType second_argument_type; typedef IntegerType second_argument_type;
typedef IntegerType result_type; typedef IntegerType result_type;
#endif #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); return boost::integer::gcd(a, b);
} }

View File

@ -542,6 +542,15 @@ void variadics()
BOOST_TEST_EQ(boost::integer::gcd_range(i, i + 4).second, i + 4); 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).first, 11704);
BOOST_TEST_EQ(boost::integer::lcm_range(i, i + 4).second, i + 4); 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 #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::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); BOOST_TEST_EQ(boost::integer::lcm(i[0], i[1], i[2], i[3]), 11704);