[boost][range] - ticket 5544 - fix for termination of irange - done properly for negative step sizes.

[SVN r72097]
This commit is contained in:
Neil Groves
2011-05-22 19:59:59 +00:00
parent df1a3a334f
commit 5ed6116490
2 changed files with 44 additions and 24 deletions

View File

@ -124,13 +124,11 @@ namespace boost
typedef typename base_t::difference_type difference_type; typedef typename base_t::difference_type difference_type;
typedef typename base_t::reference reference; typedef typename base_t::reference reference;
integer_iterator_with_step(value_type first, value_type step, difference_type step_size) integer_iterator_with_step(value_type first, difference_type step, value_type step_size)
: m_first(first) : m_first(first)
, m_step(step) , m_step(step)
, m_step_size(step_size) , m_step_size(step_size)
{ {
BOOST_ASSERT( step >= 0 );
BOOST_ASSERT( step_size != 0 );
} }
private: private:
@ -213,17 +211,18 @@ namespace boost
{ {
BOOST_ASSERT( step_size != 0 ); BOOST_ASSERT( step_size != 0 );
BOOST_ASSERT( (step_size > 0) ? (last >= first) : (last <= first) ); BOOST_ASSERT( (step_size > 0) ? (last >= first) : (last <= first) );
typedef typename range_detail::integer_iterator_with_step<Integer> iterator_t; typedef typename range_detail::integer_iterator_with_step<Integer> iterator_t;
const std::ptrdiff_t l = static_cast<std::ptrdiff_t>(last); const std::ptrdiff_t sz = static_cast<std::ptrdiff_t>(step_size >= 0 ? step_size : -step_size);
const std::ptrdiff_t f = static_cast<std::ptrdiff_t>(first); const Integer l = step_size >= 0 ? last : first;
const std::ptrdiff_t sz = static_cast<std::ptrdiff_t>(step_size); const Integer f = step_size >= 0 ? first : last;
const std::ptrdiff_t last_step = (l + ((l-f) % sz) - f) / sz; const std::ptrdiff_t num_steps = (l + ((l-f) % sz) - f) / sz;
BOOST_ASSERT(num_steps >= 0);
return strided_integer_range<Integer>( return strided_integer_range<Integer>(
iterator_t(first, 0, step_size), iterator_t(first, 0, step_size),
iterator_t(first, last_step, step_size)); iterator_t(first, num_steps, step_size));
} }
} // namespace boost } // namespace boost

View File

@ -14,7 +14,6 @@
#include <boost/range/end.hpp> #include <boost/range/end.hpp>
#include <boost/test/test_tools.hpp> #include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <iostream>
#include <vector> #include <vector>
namespace boost namespace boost
@ -35,27 +34,38 @@ namespace boost
BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(),
reference.begin(), reference.end() ); reference.begin(), reference.end() );
} }
template<typename Integer>
std::ptrdiff_t test_irange_calculate_num_steps(Integer first, Integer last, int step)
{
const std::ptrdiff_t sz = static_cast<std::ptrdiff_t>(step >= 0 ? step : -step);
const std::ptrdiff_t l = static_cast<std::ptrdiff_t>(step >= 0 ? last : first);
const std::ptrdiff_t f = static_cast<std::ptrdiff_t>(step >= 0 ? first : last);
return (l + ((l-f) % sz) - f) / sz;
}
// Test an integer range with a runtime specified step size. // Test an integer range with a runtime specified step size.
template<typename Integer> template<typename Integer, typename IntegerInput>
void test_irange_impl(Integer first, Integer last, int step) void test_irange_impl(IntegerInput first, IntegerInput last, int step)
{ {
BOOST_ASSERT( step != 0 ); BOOST_ASSERT( step != 0 );
// Skip tests that have negative values if the type is
// unsigned
if ((static_cast<IntegerInput>(static_cast<Integer>(first)) != first)
|| (static_cast<IntegerInput>(static_cast<Integer>(last)) != last))
return;
std::vector<Integer> reference; std::vector<Integer> reference;
if (step > 0)
{ const std::ptrdiff_t num_steps = test_irange_calculate_num_steps(first, last, step);
for (Integer i = first; i < last; i += step) Integer current_value = first;
reference.push_back(i); for (std::ptrdiff_t i = 0; i < num_steps; ++i, current_value += step)
} reference.push_back(current_value);
else
{
for (Integer i = first; i > last; i += step)
reference.push_back(i);
}
std::vector<Integer> test; std::vector<Integer> test;
boost::push_back(test, boost::irange(first, last, step)); boost::push_back(test, boost::irange(first, last, step));
BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(),
reference.begin(), reference.end() ); reference.begin(), reference.end() );
} }
@ -114,6 +124,10 @@ namespace boost
test_irange(0, 2, 2); test_irange(0, 2, 2);
test_irange(2, 0, -2); test_irange(2, 0, -2);
test_irange(0, 9, 2); test_irange(0, 9, 2);
test_irange(9, 0, -2);
test_irange(-9, 0, 2);
test_irange(-9, 9, 2);
test_irange(9, -9, -2);
test_irange(10, 20, 5); test_irange(10, 20, 5);
test_irange(20, 10, -5); test_irange(20, 10, -5);
@ -123,6 +137,13 @@ namespace boost
test_irange(0, 3, 3); test_irange(0, 3, 3);
test_irange(0, 4, 3); test_irange(0, 4, 3);
test_irange(0, 10, 3); test_irange(0, 10, 3);
test_irange(0, 0, -3);
test_irange(0, -1, -3);
test_irange(0, -2, -3);
test_irange(0, -3, -3);
test_irange(0, -4, -3);
test_irange(0, -10, -3);
} }
} // namespace boost } // namespace boost