$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r72097 - in trunk: boost/range libs/range/test
From: neil_at_[hidden]
Date: 2011-05-22 16:00:00
Author: neilgroves
Date: 2011-05-22 15:59:59 EDT (Sun, 22 May 2011)
New Revision: 72097
URL: http://svn.boost.org/trac/boost/changeset/72097
Log:
[boost][range] - ticket 5544 - fix for termination of irange - done properly for negative step sizes.
Text files modified: 
   trunk/boost/range/irange.hpp     |    19 +++++++--------                         
   trunk/libs/range/test/irange.cpp |    49 ++++++++++++++++++++++++++++----------- 
   2 files changed, 44 insertions(+), 24 deletions(-)
Modified: trunk/boost/range/irange.hpp
==============================================================================
--- trunk/boost/range/irange.hpp	(original)
+++ trunk/boost/range/irange.hpp	2011-05-22 15:59:59 EDT (Sun, 22 May 2011)
@@ -124,13 +124,11 @@
             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 @@
     {
         BOOST_ASSERT( step_size != 0 );
         BOOST_ASSERT( (step_size > 0) ? (last >= first) : (last <= first) );
-
+        
         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 f = static_cast<std::ptrdiff_t>(first);
-        const std::ptrdiff_t sz = static_cast<std::ptrdiff_t>(step_size);
-        const std::ptrdiff_t last_step = (l + ((l-f) % sz) - f) / sz;
-
+        const std::ptrdiff_t sz = static_cast<std::ptrdiff_t>(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<Integer>(
             iterator_t(first, 0, step_size),
-            iterator_t(first, last_step, step_size));
+            iterator_t(first, num_steps, step_size));
     }
 
 } // namespace boost
Modified: trunk/libs/range/test/irange.cpp
==============================================================================
--- trunk/libs/range/test/irange.cpp	(original)
+++ trunk/libs/range/test/irange.cpp	2011-05-22 15:59:59 EDT (Sun, 22 May 2011)
@@ -14,7 +14,6 @@
 #include <boost/range/end.hpp>
 #include <boost/test/test_tools.hpp>
 #include <boost/test/unit_test.hpp>
-#include <iostream>
 #include <vector>
 
 namespace boost
@@ -35,27 +34,38 @@
         BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.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.
-    template<typename Integer>
-    void test_irange_impl(Integer first, Integer last, int step)
+    template<typename Integer, typename IntegerInput>
+    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<IntegerInput>(static_cast<Integer>(first)) != first)
+        ||  (static_cast<IntegerInput>(static_cast<Integer>(last)) != last))
+            return;
+        
         std::vector<Integer> 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<Integer> 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 @@
         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 @@
         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