Add `thrust::next` and `thrust::prev`.
Bug
MODIFY
testing/advance.cu
testing/advance.cu
// TODO expand this with other iterator types (forward, bidirectional, etc.)
template <typename Vector>
-void TestAdvance(void)
+void TestAdvance()
{
typedef typename Vector::value_type T;
typedef typename Vector::iterator Iterator;
- Vector v(100);
+ Vector v(10);
thrust::sequence(v.begin(), v.end());
Iterator i = v.begin();
- thrust::advance(i, 7);
+ thrust::advance(i, 1);
- ASSERT_EQUAL(*i, T(7));
+ ASSERT_EQUAL(*i, T(1));
- thrust::advance(i, 13);
+ thrust::advance(i, 8);
- ASSERT_EQUAL(*i, T(20));
+ ASSERT_EQUAL(*i, T(9));
- thrust::advance(i, -10);
+ thrust::advance(i, -4);
- ASSERT_EQUAL(*i, T(10));
+ ASSERT_EQUAL(*i, T(5));
}
DECLARE_VECTOR_UNITTEST(TestAdvance);
+template <typename Vector>
+void TestNext()
+{
+ typedef typename Vector::value_type T;
+ typedef typename Vector::iterator Iterator;
+
+ Vector v(10);
+ thrust::sequence(v.begin(), v.end());
+
+ Iterator const i0 = v.begin();
+
+ Iterator const i1 = thrust::next(i0);
+
+ ASSERT_EQUAL(*i0, T(0));
+ ASSERT_EQUAL(*i1, T(1));
+
+ Iterator const i2 = thrust::next(i1, 8);
+
+ ASSERT_EQUAL(*i0, T(0));
+ ASSERT_EQUAL(*i1, T(1));
+ ASSERT_EQUAL(*i2, T(9));
+
+ Iterator const i3 = thrust::next(i2, -4);
+
+ ASSERT_EQUAL(*i0, T(0));
+ ASSERT_EQUAL(*i1, T(1));
+ ASSERT_EQUAL(*i2, T(9));
+ ASSERT_EQUAL(*i3, T(5));
+}
+DECLARE_VECTOR_UNITTEST(TestNext);
+
+template <typename Vector>
+void TestPrev()
+{
+ typedef typename Vector::value_type T;
+ typedef typename Vector::iterator Iterator;
+
+ Vector v(10);
+ thrust::sequence(v.begin(), v.end());
+
+ Iterator const i0 = v.end();
+
+ Iterator const i1 = thrust::prev(i0);
+
+ ASSERT_EQUAL_QUIET(i0, v.end());
+ ASSERT_EQUAL(*i1, T(9));
+
+ Iterator const i2 = thrust::prev(i1, 8);
+
+ ASSERT_EQUAL_QUIET(i0, v.end());
+ ASSERT_EQUAL(*i1, T(9));
+ ASSERT_EQUAL(*i2, T(1));
+
+ Iterator const i3 = thrust::prev(i2, -4);
+
+ ASSERT_EQUAL_QUIET(i0, v.end());
+ ASSERT_EQUAL(*i1, T(9));
+ ASSERT_EQUAL(*i2, T(1));
+ ASSERT_EQUAL(*i3, T(5));
+}
+DECLARE_VECTOR_UNITTEST(TestPrev);
+

MODIFY
thrust/advance.h
thrust/advance.h
namespace thrust
{
-
/*! \addtogroup iterators
* \{
*/
@@ -65,6 +64,74 @@ template <typename InputIterator, typename Distance>
__host__ __device__
void advance(InputIterator& i, Distance n);
+/*! \p next(i, n) returns the \p n th successor of the iterator \p i.
+ *
+ * \param i An iterator.
+ * \param n The number of elements to advance.
+ *
+ * \tparam InputIterator must meet the <a href="https://en.cppreference.com/w/cpp/named_req/InputIterator">InputIterator</a>.
+ *
+ * \pre \p n shall be negative only for bidirectional and random access iterators.
+ *
+ * The following code snippet demonstrates how to use \p next.
+ *
+ * \code
+ * #include <thrust/advance.h>
+ * #include <thrust/device_vector.h>
+ * ...
+ * thrust::device_vector<int> vec(13);
+ * thrust::device_vector<int>::iterator i0 = vec.begin();
+ *
+ * auto i1 = thrust::next(i0);
+ *
+ * // i0 - vec.begin() == 0
+ * // i1 - vec.begin() == 1
+ * \endcode
+ *
+ * \see https://en.cppreference.com/w/cpp/iterator/next
+ */
+#if 0 // Doxygen only
+template <typename InputIterator, typename Distance>
+__host__ __device__
+InputIterator next(
+ InputIterator i
+, typename iterator_traits<InputIterator>::difference_type n = 1
+);
+#endif
+
+/*! \p prev(i, n) returns the \p n th predecessor of the iterator \p i.
+ *
+ * \param i An iterator.
+ * \param n The number of elements to descend.
+ *
+ * \tparam BidirectionalIterator must meet the <a href="https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator">BidirectionalIterator</a>.
+ *
+ * The following code snippet demonstrates how to use \p prev.
+ *
+ * \code
+ * #include <thrust/advance.h>
+ * #include <thrust/device_vector.h>
+ * ...
+ * thrust::device_vector<int> vec(13);
+ * thrust::device_vector<int>::iterator i0 = vec.end();
+ *
+ * auto i1 = thrust::prev(i0);
+ *
+ * // vec.end() - i0 == 0
+ * // vec.end() - i1 == 1
+ * \endcode
+ *
+ * \see https://en.cppreference.com/w/cpp/iterator/prev
+ */
+#if 0 // Doxygen only
+template <typename BidirectionalIterator, typename Distance>
+__host__ __device__
+BidirectionalIterator prev(
+ BidirectionalIterator i
+, typename iterator_traits<BidirectionalIterator>::difference_type n = 1
+);
+#endif
+
/*! \} // end iterators
*/

MODIFY
thrust/detail/advance.inl
thrust/detail/advance.inl
#include <thrust/detail/config.h>
#include <thrust/advance.h>
#include <thrust/system/detail/generic/advance.h>
+#include <thrust/iterator/iterator_traits.h>
+#include <thrust/detail/type_traits.h>
+#include <thrust/detail/type_traits/has_nested_type.h>
+#include <thrust/detail/type_traits/pointer_traits.h>
namespace thrust
{
+__THRUST_DEFINE_HAS_NESTED_TYPE(has_difference_type, difference_type)
template <typename InputIterator, typename Distance>
__host__ __device__
void advance(InputIterator& i, Distance n)
{
thrust::system::detail::generic::advance(i, n);
-} // end advance()
+}
+template <typename InputIterator>
+__host__ __device__
+InputIterator next(
+ InputIterator i
+, typename iterator_traits<InputIterator>::difference_type n = 1
+)
+{
+ thrust::system::detail::generic::advance(i, n);
+ return i;
+}
+
+template <typename BidirectionalIterator>
+__host__ __device__
+BidirectionalIterator prev(
+ BidirectionalIterator i
+, typename iterator_traits<BidirectionalIterator>::difference_type n = 1
+)
+{
+ thrust::system::detail::generic::advance(i, -n);
+ return i;
+}
+
+template <typename BidirectionalIterator>
+__host__ __device__
+typename detail::disable_if<
+ has_difference_type<iterator_traits<BidirectionalIterator> >::value
+, BidirectionalIterator
+>::type prev(
+ BidirectionalIterator i
+, typename detail::pointer_traits<BidirectionalIterator>::difference_type n = 1
+)
+{
+ thrust::system::detail::generic::advance(i, -n);
+ return i;
+}
-} // end namespace thrust
+} // namespace thrust

Add `thrust::next` and `thrust::prev`.

Bug 2379510