1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
/*
* Copyright 2020-2021 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.
*/
#pragma once
#include <thrust/detail/config.h>
#include <thrust/iterator/iterator_adaptor.h>
THRUST_NAMESPACE_BEGIN
template <typename InputFunction, typename OutputFunction, typename Iterator>
class transform_input_output_iterator;
namespace detail
{
// Proxy reference that invokes InputFunction when reading from and
// OutputFunction when writing to the dereferenced iterator
template <typename InputFunction, typename OutputFunction, typename Iterator>
class transform_input_output_iterator_proxy
{
using iterator_value_type = typename thrust::iterator_value<Iterator>::type;
// std::result_of is deprecated in 2017, replace with std::invoke_result
#if THRUST_CPP_DIALECT < 2017
using Value = typename std::result_of<InputFunction(iterator_value_type)>::type;
#else
using Value = std::invoke_result_t<InputFunction, iterator_value_type>;
#endif
public:
__host__ __device__
transform_input_output_iterator_proxy(const Iterator& io, InputFunction input_function, OutputFunction output_function)
: io(io), input_function(input_function), output_function(output_function)
{
}
transform_input_output_iterator_proxy(const transform_input_output_iterator_proxy&) = default;
__thrust_exec_check_disable__
__host__ __device__
operator Value const() const
{
return input_function(*io);
}
__thrust_exec_check_disable__
template <typename T>
__host__ __device__
transform_input_output_iterator_proxy operator=(const T& x)
{
*io = output_function(x);
return *this;
}
__thrust_exec_check_disable__
__host__ __device__
transform_input_output_iterator_proxy operator=(const transform_input_output_iterator_proxy& x)
{
*io = output_function(x);
return *this;
}
private:
Iterator io;
InputFunction input_function;
OutputFunction output_function;
};
// Compute the iterator_adaptor instantiation to be used for transform_input_output_iterator
template <typename InputFunction, typename OutputFunction, typename Iterator>
struct transform_input_output_iterator_base
{
private:
using iterator_value_type = typename thrust::iterator_value<Iterator>::type;
public:
typedef thrust::iterator_adaptor
<
transform_input_output_iterator<InputFunction, OutputFunction, Iterator>
, Iterator
// std::result_of is deprecated in 2017, replace with std::invoke_result
#if THRUST_CPP_DIALECT < 2017
, typename std::result_of<InputFunction(iterator_value_type)>::type
#else
, std::invoke_result_t<InputFunction, iterator_value_type>
#endif
, thrust::use_default
, thrust::use_default
, transform_input_output_iterator_proxy<InputFunction, OutputFunction, Iterator>
> type;
};
// Register transform_input_output_iterator_proxy with 'is_proxy_reference' from
// type_traits to enable its use with algorithms.
template <typename InputFunction, typename OutputFunction, typename Iterator>
struct is_proxy_reference<
transform_input_output_iterator_proxy<InputFunction, OutputFunction, Iterator> >
: public thrust::detail::true_type {};
} // end detail
THRUST_NAMESPACE_END
|