| 2125 | |
| 2126 | template <typename Func, typename Return, typename... Args> |
| 2127 | struct vectorize_helper { |
| 2128 | |
| 2129 | // NVCC for some reason breaks if NVectorized is private |
| 2130 | #ifdef __CUDACC__ |
| 2131 | public: |
| 2132 | #else |
| 2133 | private: |
| 2134 | #endif |
| 2135 | |
| 2136 | static constexpr size_t N = sizeof...(Args); |
| 2137 | static constexpr size_t NVectorized = constexpr_sum(vectorize_arg<Args>::vectorize...); |
| 2138 | static_assert( |
| 2139 | NVectorized >= 1, |
| 2140 | "pybind11::vectorize(...) requires a function with at least one vectorizable argument"); |
| 2141 | |
| 2142 | public: |
| 2143 | template <typename T, |
| 2144 | // SFINAE to prevent shadowing the copy constructor. |
| 2145 | typename = detail::enable_if_t< |
| 2146 | !std::is_same<vectorize_helper, typename std::decay<T>::type>::value>> |
| 2147 | explicit vectorize_helper(T &&f) : f(std::forward<T>(f)) {} |
| 2148 | |
| 2149 | object operator()(typename vectorize_arg<Args>::type... args) { |
| 2150 | return run(args..., |
| 2151 | make_index_sequence<N>(), |
| 2152 | select_indices<vectorize_arg<Args>::vectorize...>(), |
| 2153 | make_index_sequence<NVectorized>()); |
| 2154 | } |
| 2155 | |
| 2156 | private: |
| 2157 | remove_reference_t<Func> f; |
| 2158 | |
| 2159 | // Internal compiler error in MSVC 19.16.27025.1 (Visual Studio 2017 15.9.4), when compiling |
| 2160 | // with "/permissive-" flag when arg_call_types is manually inlined. |
| 2161 | using arg_call_types = std::tuple<typename vectorize_arg<Args>::call_type...>; |
| 2162 | template <size_t Index> |
| 2163 | using param_n_t = typename std::tuple_element<Index, arg_call_types>::type; |
| 2164 | |
| 2165 | using returned_array = vectorize_returned_array<Func, Return, Args...>; |
| 2166 | |
| 2167 | // Runs a vectorized function given arguments tuple and three index sequences: |
| 2168 | // - Index is the full set of 0 ... (N-1) argument indices; |
| 2169 | // - VIndex is the subset of argument indices with vectorized parameters, letting us access |
| 2170 | // vectorized arguments (anything not in this sequence is passed through) |
| 2171 | // - BIndex is a incremental sequence (beginning at 0) of the same size as VIndex, so that |
| 2172 | // we can store vectorized buffer_infos in an array (argument VIndex has its buffer at |
| 2173 | // index BIndex in the array). |
| 2174 | template <size_t... Index, size_t... VIndex, size_t... BIndex> |
| 2175 | object run(typename vectorize_arg<Args>::type &...args, |
| 2176 | index_sequence<Index...> i_seq, |
| 2177 | index_sequence<VIndex...> vi_seq, |
| 2178 | index_sequence<BIndex...> bi_seq) { |
| 2179 | |
| 2180 | // Pointers to values the function was called with; the vectorized ones set here will start |
| 2181 | // out as array_t<T> pointers, but they will be changed them to T pointers before we make |
| 2182 | // call the wrapped function. Non-vectorized pointers are left as-is. |
| 2183 | std::array<void *, N> params{{reinterpret_cast<void *>(&args)...}}; |
| 2184 |
nothing calls this directly
no test coverage detected