1/*
2 *  Copyright 2008-2013 NVIDIA Corporation
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 *  distributed under the License is distributed on an "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *  See the License for the specific language governing permissions and
14 *  limitations under the License.
15 */
16
17
18#pragma once
19
20#include <thrust/detail/config.h>
21#include <thrust/system/detail/generic/transform_scan.h>
22#include <thrust/scan.h>
23#include <thrust/iterator/transform_iterator.h>
24#include <thrust/detail/type_traits.h>
25#include <thrust/detail/type_traits/function_traits.h>
26#include <thrust/detail/type_traits/iterator/is_output_iterator.h>
27
28namespace thrust
29{
30namespace system
31{
32namespace detail
33{
34namespace generic
35{
36
37
38template<typename ExecutionPolicy,
39         typename InputIterator,
40         typename OutputIterator,
41         typename UnaryFunction,
42         typename BinaryFunction>
43__host__ __device__
44  OutputIterator transform_inclusive_scan(thrust::execution_policy<ExecutionPolicy> &exec,
45                                          InputIterator first,
46                                          InputIterator last,
47                                          OutputIterator result,
48                                          UnaryFunction unary_op,
49                                          BinaryFunction binary_op)
50{
51  // the pseudocode for deducing the type of the temporary used below:
52  //
53  // if UnaryFunction is AdaptableUnaryFunction
54  //   TemporaryType = AdaptableUnaryFunction::result_type
55  // else if OutputIterator is a "pure" output iterator
56  //   TemporaryType = InputIterator::value_type
57  // else
58  //   TemporaryType = OutputIterator::value_type
59  //
60  // XXX upon c++0x, TemporaryType needs to be:
61  // result_of_adaptable_function<UnaryFunction>::type
62
63  typedef typename thrust::detail::eval_if<
64    thrust::detail::has_result_type<UnaryFunction>::value,
65    thrust::detail::result_type<UnaryFunction>,
66    thrust::detail::eval_if<
67      thrust::detail::is_output_iterator<OutputIterator>::value,
68      thrust::iterator_value<InputIterator>,
69      thrust::iterator_value<OutputIterator>
70    >
71  >::type ValueType;
72
73  thrust::transform_iterator<UnaryFunction, InputIterator, ValueType> _first(first, unary_op);
74  thrust::transform_iterator<UnaryFunction, InputIterator, ValueType> _last(last, unary_op);
75
76  return thrust::inclusive_scan(exec, _first, _last, result, binary_op);
77} // end transform_inclusive_scan()
78
79
80template<typename ExecutionPolicy,
81         typename InputIterator,
82         typename OutputIterator,
83         typename UnaryFunction,
84         typename T,
85         typename AssociativeOperator>
86__host__ __device__
87  OutputIterator transform_exclusive_scan(thrust::execution_policy<ExecutionPolicy> &exec,
88                                          InputIterator first,
89                                          InputIterator last,
90                                          OutputIterator result,
91                                          UnaryFunction unary_op,
92                                          T init,
93                                          AssociativeOperator binary_op)
94{
95  // the pseudocode for deducing the type of the temporary used below:
96  //
97  // if UnaryFunction is AdaptableUnaryFunction
98  //   TemporaryType = AdaptableUnaryFunction::result_type
99  // else if OutputIterator is a "pure" output iterator
100  //   TemporaryType = InputIterator::value_type
101  // else
102  //   TemporaryType = OutputIterator::value_type
103  //
104  // XXX upon c++0x, TemporaryType needs to be:
105  // result_of_adaptable_function<UnaryFunction>::type
106
107  typedef typename thrust::detail::eval_if<
108    thrust::detail::has_result_type<UnaryFunction>::value,
109    thrust::detail::result_type<UnaryFunction>,
110    thrust::detail::eval_if<
111      thrust::detail::is_output_iterator<OutputIterator>::value,
112      thrust::iterator_value<InputIterator>,
113      thrust::iterator_value<OutputIterator>
114    >
115  >::type ValueType;
116
117  thrust::transform_iterator<UnaryFunction, InputIterator, ValueType> _first(first, unary_op);
118  thrust::transform_iterator<UnaryFunction, InputIterator, ValueType> _last(last, unary_op);
119
120  return thrust::exclusive_scan(exec, _first, _last, result, init, binary_op);
121} // end transform_exclusive_scan()
122
123
124} // end namespace generic
125} // end namespace detail
126} // end namespace system
127} // end namespace thrust
128
129