zip_transform_iterator#

template<class _Fn, class ..._Iterators>
class zip_transform_iterator#

zip_transform_iterator is an iterator which represents the result of a transformation of a set of sequences with a given function.

This iterator is useful for creating a range filled with the result of applying an operation to another range without either explicitly storing it in memory, or explicitly executing the transformation. Using zip_transform_iterator facilitates kernel fusion by deferring the execution of a transformation until the value is needed while saving both memory capacity and bandwidth.

zip_transform_iterator is morally equivalent to a combination of transform_iterator and zip_iterator

template <class Fn, class... Iterators>
using zip_transform_iterator = cuda::transform_iterator<cuda::zip_iterator<Iterators...>, cuda::zip_function<Fn>>;

zip_transform_iterator has the additional benefit that it does not require an artificial zip_function to work and more importantly does not need to materialize the result of dereferencing the stored iterators when passing them to the stored function.

The following code snippet demonstrates how to create a zip_transform_iterator which represents the result of “zipping” multiple ranges together.

#include <cuda/iterator>
#include <thrust/device_vector.h>

struct SumArgs {
  __host__ __device__ float operator()(float a, float b, float c) const noexcept {
    return a + b + c;
  }
};

thrust::device_vector<float> A{0.f, 1.f, 2.f};
thrust::device_vector<float> B{1.f, 2.f, 3.f};
thrust::device_vector<float> C{2.f, 3.f, 4.f};

cuda::zip_transform_iterator iter{SumArgs{}, A.begin(), B.begin(), C.begin()};

*iter;   // returns (3.f)
iter[0]; // returns (3.f)
iter[1]; // returns (6.f)
iter[2]; // returns (9.f)
// iter[3] is an out-of-bounds error

This example shows how to use zip_transform_iterator to copy multiple ranges with a single call to thrust::copy.

#include <cuda/iterator>
#include <thrust/device_vector.h>

int main()
{
  struct SumArgs {
    __host__ __device__ float operator()(float a, float b, float c) const noexcept {
      return a + b + c;
    }
  };

  thrust::device_vector<float> A{0.f, 1.f, 2.f};
  thrust::device_vector<float> B{1.f, 2.f, 3.f};
  thrust::device_vector<float> C{2.f, 3.f, 4.f};
  thrust::device_vector<float> out(3);

  cuda::zip_transform_iterator iter{SumArgs{}, A.begin(), B.begin(), C.begin()}
  thrust::copy(iter, iter + 3, out.begin());

  // out is now [3.0f, 6.0f, 9.0f]

  return 0;
}

Public Types

using iterator_concept = decltype(::cuda::__get_zip_iterator_concept<_Iterators...>())#
using iterator_category = decltype(::cuda::__get_zip_transform_iterator_category<_Fn, _Iterators...>())#
using difference_type = ::cuda::std::common_type_t<::cuda::std::iter_difference_t<_Iterators>...>#
using value_type = ::cuda::std::remove_cvref_t<::cuda::std::invoke_result_t<_Fn&, ::cuda::std::iter_reference_t<_Iterators>...>>#
using reference = ::cuda::std::invoke_result_t<_Fn&, ::cuda::std::iter_reference_t<_Iterators>...>#
using pointer = void#

Public Functions

template<class _Fn2 = _Fn, ::cuda::std::enable_if_t<::cuda::std::default_initializable<_Fn2> && __zip_iter_constraints<_Iterators...>::__all_default_initializable, int> = 0>
inline constexpr zip_transform_iterator(
) noexcept(::cuda::std::is_nothrow_default_constructible_v<_Fn2> && __zip_iter_constraints<_Iterators...>::__all_nothrow_default_constructible)#

Default-constructs a zip_transform_iterator by value-initializing the functor and all stored iterators.

inline explicit constexpr zip_transform_iterator(
_Fn __fun,
__tuple_or_pair<_Iterators...> __iters,
)#

Constructs a zip_transform_iterator from a tuple of iterators.

Parameters:

__iters – A tuple or pair of iterators

template<size_t _NumIterators = sizeof...(_Iterators), ::cuda::std::enable_if_t<(_NumIterators == 2), int> = 0>
inline explicit constexpr zip_transform_iterator(
_Fn __fun,
::cuda::std::tuple<_Iterators...> __iters,
)#

Constructs a zip_transform_iterator from a tuple of iterators.

Parameters:

__iters – A tuple of iterators

inline explicit constexpr zip_transform_iterator(
_Fn __fun,
_Iterators... __iters,
)#

Constructs a zip_transform_iterator from variadic set of iterators.

Parameters:

__iters – The input iterators

inline constexpr reference operator*(
) const noexcept(::cuda::std::is_nothrow_invocable_v<_Fn&, ::cuda::std::iter_reference_t<const _Iterators>...>)#

Invokes the stored function with the result of dereferencing the stored iterators.

template<class _Constraints = __zip_iter_constraints<_Iterators...>, ::cuda::std::enable_if_t<_Constraints::__all_random_access, int> = 0>
inline constexpr reference operator[](
difference_type __n,
) const noexcept(noexcept(::cuda::std::apply(__zip_transform_op_subscript{__n, const_cast<_Fn&>(*__func_)}, __current_)))#

Invokes the stored function with the result of dereferencing the stored iterators advanced by an offset.

Parameters:

__n – The additional offset

inline constexpr zip_transform_iterator &operator++(
) noexcept(noexcept(::cuda::std::apply(__zip_op_increment{}, __current_)))#

Increments all stored iterators.

inline constexpr auto operator++(int)#

Increments all stored iterators.

Returns:

A copy of the original zip_transform_iterator if possible

template<class _Constraints = __zip_iter_constraints<_Iterators...>, ::cuda::std::enable_if_t<_Constraints::__all_bidirectional, int> = 0>
inline constexpr zip_transform_iterator &operator--(
) noexcept(noexcept(::cuda::std::apply(__zip_op_decrement{}, __current_)))#

Decrements all stored iterators.

template<class _Constraints = __zip_iter_constraints<_Iterators...>, ::cuda::std::enable_if_t<_Constraints::__all_bidirectional, int> = 0>
inline constexpr zip_transform_iterator operator--(
int,
)#

Decrements all stored iterators.

template<class _Constraints = __zip_iter_constraints<_Iterators...>, ::cuda::std::enable_if_t<_Constraints::__all_random_access, int> = 0>
inline constexpr zip_transform_iterator &operator+=(
difference_type __n,
) noexcept(noexcept(::cuda::std::apply(__zip_op_pe{__n}, __current_)))#

Increments all stored iterators by a given number of elements.

Parameters:

__n – The number of elements to increment

template<class _Constraints = __zip_iter_constraints<_Iterators...>, ::cuda::std::enable_if_t<_Constraints::__all_random_access, int> = 0>
inline constexpr zip_transform_iterator &operator-=(
difference_type __n,
)#

Decrements all stored iterators by a given number of elements.

Parameters:

__n – The number of elements to decrement

Friends

template<class _Constraints = __zip_iter_constraints<_Iterators...>>
inline friend constexpr auto operator+(
const zip_transform_iterator &__iter,
difference_type __n,
) -> zip_transform_iterator#
requires (_Constraints::__all_random_access)

Returns a copy of a zip_transform_iterator incremented by a given number of elements.

Parameters:
template<class _Constraints = __zip_iter_constraints<_Iterators...>>
inline friend constexpr auto operator+(
difference_type __n,
const zip_transform_iterator &__iter,
) -> zip_transform_iterator#
requires (_Constraints::__all_random_access)

Returns a copy of a zip_transform_iterator incremented by a given number of elements.

Parameters:
template<class _Constraints = __zip_iter_constraints<_Iterators...>>
inline friend constexpr auto operator-(
const zip_transform_iterator &__iter,
difference_type __n,
) -> zip_transform_iterator#
requires (_Constraints::__all_random_access)

Returns a copy of a zip_transform_iterator decremented by a given number of elements.

Parameters:
template<class _Constraints = __zip_iter_constraints<_Iterators...>>
inline friend constexpr auto operator-(
const zip_transform_iterator &__n,
const zip_transform_iterator &__y,
) -> difference_type#
requires (_Constraints::__all_sized_sentinel)

Returns the distance between two zip_transform_iterators.

Returns:

The minimal distance between any of the stored iterators

template<class _Constraints = __zip_iter_constraints<_Iterators...>>
inline friend constexpr auto operator==(
const zip_transform_iterator &__n,
const zip_transform_iterator &__y,
) -> bool#
requires (_Constraints::__all_equality_comparable)

Compares two zip_transform_iterator for equality by comparing the tuple of stored iterators.

template<class _Constraints = __zip_iter_constraints<_Iterators...>>
inline friend constexpr auto operator<(
const zip_transform_iterator &__n,
const zip_transform_iterator &__y,
) -> bool#
requires (_Constraints::__all_random_access)

Compares two zip_transform_iterator for less than by comparing the tuple of stored iterators.

template<class _Constraints = __zip_iter_constraints<_Iterators...>>
inline friend constexpr auto operator>(
const zip_transform_iterator &__n,
const zip_transform_iterator &__y,
) -> bool#
requires (_Constraints::__all_random_access)

Compares two zip_transform_iterator for greater than by comparing the tuple of stored iterators.

template<class _Constraints = __zip_iter_constraints<_Iterators...>>
inline friend constexpr auto operator<=(
const zip_transform_iterator &__n,
const zip_transform_iterator &__y,
) -> bool#
requires (_Constraints::__all_random_access)

Compares two zip_transform_iterator for less equal by comparing the tuple of stored iterators.

template<class _Constraints = __zip_iter_constraints<_Iterators...>>
inline friend constexpr auto operator>=(
const zip_transform_iterator &__n,
const zip_transform_iterator &__y,
) -> bool#
requires (_Constraints::__all_random_access)

Compares two zip_transform_iterator for greater equal by comparing the tuple of stored iterators.