thrust/iterator/counting_iterator.h
File members: thrust/iterator/counting_iterator.h
/*
* Copyright 2008-2013 NVIDIA Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright David Abrahams 2003.
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying NOTICE file for the complete license)
*
* For more information, see http://www.boost.org
*/
#pragma once
#include <thrust/detail/config.h>
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
# pragma GCC system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
# pragma clang system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
# pragma system_header
#endif // no system header
#include <thrust/detail/type_traits.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/iterator/iterator_adaptor.h>
#include <thrust/iterator/iterator_traits.h>
#include <cuda/std/cstddef>
#include <cuda/std/type_traits>
#include <cuda/type_traits>
THRUST_NAMESPACE_BEGIN
template <typename Incrementable, typename System, typename Traversal, typename Difference>
class counting_iterator;
namespace detail
{
template <typename Number>
using counting_iterator_difference_type =
::cuda::std::_If<::cuda::std::is_integral_v<Number> && sizeof(Number) < sizeof(int), int, ::cuda::std::ptrdiff_t>;
template <typename Incrementable, typename System, typename Traversal, typename Difference>
struct make_counting_iterator_base
{
using system =
typename eval_if<::cuda::std::is_same<System, use_default>::value, identity_<any_system_tag>, identity_<System>>::type;
using traversal = replace_if_use_default<Traversal, ::cuda::std::type_identity<random_access_traversal_tag>>;
using difference =
replace_if_use_default<Difference, ::cuda::std::type_identity<counting_iterator_difference_type<Incrementable>>>;
// our implementation departs from Boost's in that counting_iterator::dereference
// returns a copy of its counter, rather than a reference to it. returning a reference
// to the internal state of an iterator causes subtle bugs (consider the temporary
// iterator created in the expression *(iter + i)) and has no compelling use case
using type =
iterator_adaptor<counting_iterator<Incrementable, System, Traversal, Difference>,
Incrementable,
Incrementable,
system,
traversal,
Incrementable,
difference>;
};
} // namespace detail
template <typename Incrementable,
typename System = use_default,
typename Traversal = use_default,
typename Difference = use_default>
class _CCCL_DECLSPEC_EMPTY_BASES counting_iterator
: public detail::make_counting_iterator_base<Incrementable, System, Traversal, Difference>::type
{
using super_t = typename detail::make_counting_iterator_base<Incrementable, System, Traversal, Difference>::type;
friend class iterator_core_access;
public:
using reference = typename super_t::reference;
using difference_type = typename super_t::difference_type;
_CCCL_HOST_DEVICE counting_iterator()
: super_t(Incrementable{})
{}
template <class OtherSystem,
detail::enable_if_convertible_t<
typename iterator_system<counting_iterator<Incrementable, OtherSystem, Traversal, Difference>>::type,
typename iterator_system<super_t>::type,
int> = 0>
_CCCL_HOST_DEVICE counting_iterator(counting_iterator<Incrementable, OtherSystem, Traversal, Difference> const& rhs)
: super_t(rhs.base())
{}
_CCCL_HOST_DEVICE explicit counting_iterator(Incrementable x)
: super_t(x)
{}
private:
_CCCL_HOST_DEVICE reference dereference() const
{
return this->base_reference();
}
// note that we implement equal specially for floating point counting_iterator
template <typename OtherSystem, typename OtherTraversal, typename OtherDifference>
_CCCL_HOST_DEVICE bool
equal(counting_iterator<Incrementable, OtherSystem, OtherTraversal, OtherDifference> const& y) const
{
if constexpr (::cuda::is_floating_point_v<Incrementable>)
{
return distance_to(y) == 0;
}
else
{
return this->base() == y.base();
}
}
template <typename OtherSystem, typename OtherTraversal, typename OtherDifference>
_CCCL_HOST_DEVICE difference_type
distance_to(counting_iterator<Incrementable, OtherSystem, OtherTraversal, OtherDifference> const& y) const
{
if constexpr (::cuda::std::is_integral<Incrementable>::value)
{
return static_cast<difference_type>(y.base()) - static_cast<difference_type>(this->base());
}
else
{
return y.base() - this->base();
}
}
};
template <typename Incrementable>
inline _CCCL_HOST_DEVICE counting_iterator<Incrementable> make_counting_iterator(Incrementable x)
{
return counting_iterator<Incrementable>(x);
}
THRUST_NAMESPACE_END