From 5ed611649091a18b87abe375fe591bfc4747859c Mon Sep 17 00:00:00 2001 From: Neil Groves Date: Sun, 22 May 2011 19:59:59 +0000 Subject: [PATCH] [boost][range] - ticket 5544 - fix for termination of irange - done properly for negative step sizes. [SVN r72097] --- include/boost/range/irange.hpp | 19 +++++++------ test/irange.cpp | 49 ++++++++++++++++++++++++---------- 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/include/boost/range/irange.hpp b/include/boost/range/irange.hpp index fe36e9d..3b5a6cc 100644 --- a/include/boost/range/irange.hpp +++ b/include/boost/range/irange.hpp @@ -124,13 +124,11 @@ namespace boost typedef typename base_t::difference_type difference_type; 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_step(step) , m_step_size(step_size) { - BOOST_ASSERT( step >= 0 ); - BOOST_ASSERT( step_size != 0 ); } private: @@ -213,17 +211,18 @@ namespace boost { BOOST_ASSERT( step_size != 0 ); BOOST_ASSERT( (step_size > 0) ? (last >= first) : (last <= first) ); - + typedef typename range_detail::integer_iterator_with_step iterator_t; - const std::ptrdiff_t l = static_cast(last); - const std::ptrdiff_t f = static_cast(first); - const std::ptrdiff_t sz = static_cast(step_size); - const std::ptrdiff_t last_step = (l + ((l-f) % sz) - f) / sz; - + const std::ptrdiff_t sz = static_cast(step_size >= 0 ? step_size : -step_size); + const Integer l = step_size >= 0 ? last : first; + const Integer f = step_size >= 0 ? first : last; + const std::ptrdiff_t num_steps = (l + ((l-f) % sz) - f) / sz; + BOOST_ASSERT(num_steps >= 0); + return strided_integer_range( iterator_t(first, 0, step_size), - iterator_t(first, last_step, step_size)); + iterator_t(first, num_steps, step_size)); } } // namespace boost diff --git a/test/irange.cpp b/test/irange.cpp index 985e07a..358a2b1 100644 --- a/test/irange.cpp +++ b/test/irange.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include namespace boost @@ -35,27 +34,38 @@ namespace boost BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), reference.begin(), reference.end() ); } + + template + std::ptrdiff_t test_irange_calculate_num_steps(Integer first, Integer last, int step) + { + const std::ptrdiff_t sz = static_cast(step >= 0 ? step : -step); + const std::ptrdiff_t l = static_cast(step >= 0 ? last : first); + const std::ptrdiff_t f = static_cast(step >= 0 ? first : last); + return (l + ((l-f) % sz) - f) / sz; + } // Test an integer range with a runtime specified step size. - template - void test_irange_impl(Integer first, Integer last, int step) + template + void test_irange_impl(IntegerInput first, IntegerInput last, int step) { BOOST_ASSERT( step != 0 ); + + // Skip tests that have negative values if the type is + // unsigned + if ((static_cast(static_cast(first)) != first) + || (static_cast(static_cast(last)) != last)) + return; + std::vector reference; - if (step > 0) - { - for (Integer i = first; i < last; i += step) - reference.push_back(i); - } - else - { - for (Integer i = first; i > last; i += step) - reference.push_back(i); - } + + const std::ptrdiff_t num_steps = test_irange_calculate_num_steps(first, last, step); + Integer current_value = first; + for (std::ptrdiff_t i = 0; i < num_steps; ++i, current_value += step) + reference.push_back(current_value); std::vector test; boost::push_back(test, boost::irange(first, last, step)); - + BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), reference.begin(), reference.end() ); } @@ -114,6 +124,10 @@ namespace boost test_irange(0, 2, 2); test_irange(2, 0, -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(20, 10, -5); @@ -123,6 +137,13 @@ namespace boost test_irange(0, 3, 3); test_irange(0, 4, 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