vecmem 1.21.0
Loading...
Searching...
No Matches
host.ipp
1/* VecMem project, part of the ACTS project (R&D line)
2 *
3 * (c) 2023-2025 CERN for the benefit of the ACTS project
4 *
5 * Mozilla Public License Version 2.0
6 */
7#pragma once
8
9// Local include(s).
10#include "vecmem/edm/details/host_traits.hpp"
11#include "vecmem/edm/details/schema_traits.hpp"
12
13// System include(s).
14#include <string>
15#include <tuple>
16#include <type_traits>
17
18namespace vecmem {
19namespace edm {
20
21template <typename... VARTYPES, template <typename> class INTERFACE>
22VECMEM_HOST host<schema<VARTYPES...>, INTERFACE>::host(
23 memory_resource& resource)
24 : m_data{details::host_alloc<VARTYPES>::make(resource)...},
25 m_resource{resource} {}
26
27template <typename... VARTYPES, template <typename> class INTERFACE>
28VECMEM_HOST auto host<schema<VARTYPES...>, INTERFACE>::size() const
29 -> size_type {
30
31 // Make sure that there are some (jagged) vector types in the container.
32 static_assert(
33 std::disjunction_v<type::details::is_vector<VARTYPES>...>,
34 "This function requires at least one (jagged) vector variable.");
35
36 // Get the size of the vector(s).
37 return details::get_host_size<VARTYPES...>(
38 m_data, std::index_sequence_for<VARTYPES...>{});
39}
40
41template <typename... VARTYPES, template <typename> class INTERFACE>
42VECMEM_HOST auto host<schema<VARTYPES...>, INTERFACE>::capacity() const
43 -> size_type {
44
45 // Make sure that there are some (jagged) vector types in the container.
46 static_assert(
47 std::disjunction_v<type::details::is_vector<VARTYPES>...>,
48 "This function requires at least one (jagged) vector variable.");
49
50 // Get the size of the vector(s).
51 return details::get_host_capacity<VARTYPES...>(
52 m_data, std::index_sequence_for<VARTYPES...>{});
53}
54
55template <typename... VARTYPES, template <typename> class INTERFACE>
56VECMEM_HOST void host<schema<VARTYPES...>, INTERFACE>::resize(size_type size) {
57
58 // Make sure that there are some (jagged) vector types in the container.
59 static_assert(
60 std::disjunction_v<type::details::is_vector<VARTYPES>...>,
61 "This function requires at least one (jagged) vector variable.");
62
63 // Resize the vector(s).
64 details::host_resize<VARTYPES...>(m_data, size,
65 std::index_sequence_for<VARTYPES...>{});
66}
67
68template <typename... VARTYPES, template <typename> class INTERFACE>
69VECMEM_HOST void host<schema<VARTYPES...>, INTERFACE>::reserve(size_type size) {
70
71 // Make sure that there are some (jagged) vector types in the container.
72 static_assert(
73 std::disjunction_v<type::details::is_vector<VARTYPES>...>,
74 "This function requires at least one (jagged) vector variable.");
75
76 // Resize the vector(s).
77 details::host_reserve<VARTYPES...>(m_data, size,
78 std::index_sequence_for<VARTYPES...>{});
79}
80
81template <typename... VARTYPES, template <typename> class INTERFACE>
82VECMEM_HOST void host<schema<VARTYPES...>, INTERFACE>::push_back(
83 const object_type& element) {
84
85 // Make sure that there are some (jagged) vector types in the container.
86 static_assert(
87 std::disjunction_v<type::details::is_vector<VARTYPES>...>,
88 "This function requires at least one (jagged) vector variable.");
89
90 // Add a new element to the container.
91 const size_type index = size();
92 resize(index + 1);
93 // Set the new element.
94 at(index) = element;
95}
96
97template <typename... VARTYPES, template <typename> class INTERFACE>
98template <std::size_t INDEX>
99VECMEM_HOST typename details::host_type_at<INDEX, VARTYPES...>::return_type
101
102 // For scalar types we don't return the array, but rather a
103 // reference to the single scalar held by the array.
104 if constexpr (type::details::is_scalar_v<typename std::tuple_element<
105 INDEX, std::tuple<VARTYPES...>>::type>) {
106 return std::get<INDEX>(m_data)[0];
107 } else {
108 return std::get<INDEX>(m_data);
109 }
110}
111
112template <typename... VARTYPES, template <typename> class INTERFACE>
113template <std::size_t INDEX>
114VECMEM_HOST
115 typename details::host_type_at<INDEX, VARTYPES...>::const_return_type
117
118 // For scalar types we don't return the array, but rather a
119 // reference to the single scalar held by the array.
120 if constexpr (type::details::is_scalar_v<typename std::tuple_element<
121 INDEX, std::tuple<VARTYPES...>>::type>) {
122 return std::get<INDEX>(m_data)[0];
123 } else {
124 return std::get<INDEX>(m_data);
125 }
126}
127
128template <typename... VARTYPES, template <typename> class INTERFACE>
129VECMEM_HOST typename host<schema<VARTYPES...>, INTERFACE>::proxy_type
131
132 // Make sure that the index is within bounds.
133 if (index >= size()) {
134 throw std::out_of_range("index (" + std::to_string(index) +
135 ") >= size (" + std::to_string(size()) + ")");
136 }
137
138 // Use the unprotected function.
139 return this->operator[](index);
140}
141
142template <typename... VARTYPES, template <typename> class INTERFACE>
143VECMEM_HOST typename host<schema<VARTYPES...>, INTERFACE>::const_proxy_type
144host<schema<VARTYPES...>, INTERFACE>::at(size_type index) const {
145
146 // Make sure that the index is within bounds.
147 if (index >= size()) {
148 throw std::out_of_range("index (" + std::to_string(index) +
149 ") >= size (" + std::to_string(size()) + ")");
150 }
151
152 // Use the unprotected function.
153 return this->operator[](index);
154}
155
156template <typename... VARTYPES, template <typename> class INTERFACE>
157VECMEM_HOST typename host<schema<VARTYPES...>, INTERFACE>::proxy_type
158host<schema<VARTYPES...>, INTERFACE>::operator[](size_type index) {
159
160 // Create the proxy.
161 return proxy_type{*this, index};
162}
163
164template <typename... VARTYPES, template <typename> class INTERFACE>
165VECMEM_HOST typename host<schema<VARTYPES...>, INTERFACE>::const_proxy_type
166host<schema<VARTYPES...>, INTERFACE>::operator[](size_type index) const {
167
168 // Create the proxy.
169 return const_proxy_type{*this, index};
170}
171
172template <typename... VARTYPES, template <typename> class INTERFACE>
173VECMEM_HOST typename host<schema<VARTYPES...>, INTERFACE>::tuple_type&
174host<schema<VARTYPES...>, INTERFACE>::variables() {
175
176 return m_data;
177}
178
179template <typename... VARTYPES, template <typename> class INTERFACE>
180VECMEM_HOST const typename host<schema<VARTYPES...>, INTERFACE>::tuple_type&
181host<schema<VARTYPES...>, INTERFACE>::variables() const {
182
183 return m_data;
184}
185
186template <typename... VARTYPES, template <typename> class INTERFACE>
187VECMEM_HOST memory_resource& host<schema<VARTYPES...>, INTERFACE>::resource()
188 const {
189
190 return m_resource;
191}
192
193} // namespace edm
194
196template <typename... VARTYPES, template <typename> class INTERFACE>
199 memory_resource&, std::index_sequence<>) {
200 // For SonarCloud: The terminal node doesn't need to do anything.
201}
202
204template <typename... VARTYPES, template <typename> class INTERFACE,
205 std::size_t I, std::size_t... Is>
206VECMEM_HOST void get_data_impl(
208 edm::data<edm::schema<VARTYPES...>>& data, memory_resource& mr,
209 std::index_sequence<I, Is...>) {
210
211 if constexpr (edm::type::details::is_jagged_vector_v<
212 typename std::tuple_element<
213 I, std::tuple<VARTYPES...>>::type>) {
214 // Make the @c vecmem::edm::data object hold on to the
215 // @c vecmem::data::jagged_vector_data object. Notice that this is a
216 // move assignment here.
217 std::get<I>(data.variables()) =
218 ::vecmem::get_data(host.template get<I>(), &mr);
219 // Set up the @c vecmem::edm::view object to point at the
220 // @c vecmem::data::jagged_vector_data object.
221 data.template get<I>() =
222 ::vecmem::get_data(std::get<I>(data.variables()));
223 } else if constexpr (edm::type::details::is_scalar<
224 typename std::tuple_element<
225 I, std::tuple<VARTYPES...>>::type>::value) {
226 // For scalar variables we just make @c vecmem::edm::view remember
227 // a pointer.
228 data.template get<I>() = &(host.template get<I>());
229 } else {
230 // For 1D vectors it's enough to make @c vecmem::edm::view have a
231 // correct @c vecmem::data::vector_view object.
232 data.template get<I>() = ::vecmem::get_data(host.template get<I>());
233 }
234 // Continue the recursion.
235 get_data_impl(host, data, mr, std::index_sequence<Is...>{});
236}
237
238template <typename... VARTYPES, template <typename> class INTERFACE>
241 memory_resource* resource) {
242
243 // Create the result object.
245 // Decide what memory resource to use for setting it up.
246 memory_resource& mr = (resource != nullptr ? *resource : host.resource());
247 // Set its size, if that's available. Note that if there are no vector
248 // variables in the container, then @c vecmem::edm::data also doesn't need
249 // a memory resource.
250 if constexpr (std::disjunction_v<
252 result = {static_cast<
253 typename edm::data<edm::schema<VARTYPES...>>::size_type>(
254 host.size()),
255 mr};
256 }
257 // Fill it with the helper function.
258 get_data_impl<VARTYPES...>(host, result, mr,
259 std::index_sequence_for<VARTYPES...>{});
260 // Return the filled object.
261 return result;
262}
263
265template <typename... VARTYPES, template <typename> class INTERFACE>
266VECMEM_HOST void get_data_impl(
268 edm::data<edm::details::add_const_t<edm::schema<VARTYPES...>>>&,
269 memory_resource&, std::index_sequence<>) {
270 // For SonarCloud: The terminal node doesn't need to do anything.
271}
272
274template <typename... VARTYPES, template <typename> class INTERFACE,
275 std::size_t I, std::size_t... Is>
276VECMEM_HOST void get_data_impl(
278 edm::data<edm::details::add_const_t<edm::schema<VARTYPES...>>>& data,
279 memory_resource& mr, std::index_sequence<I, Is...>) {
280
282 typename std::tuple_element<
283 I, std::tuple<VARTYPES...>>::type>::value) {
284 // Make the @c vecmem::edm::data object hold on to the
285 // @c vecmem::data::jagged_vector_data object. Notice that this is a
286 // move assignment here.
287 std::get<I>(data.variables()) =
288 ::vecmem::get_data(host.template get<I>(), &mr);
289 // Set up the @c vecmem::edm::view object to point at the
290 // @c vecmem::data::jagged_vector_data object.
291 data.template get<I>() =
292 ::vecmem::get_data(std::get<I>(data.variables()));
293 } else if constexpr (edm::type::details::is_scalar<
294 typename std::tuple_element<
295 I, std::tuple<VARTYPES...>>::type>::value) {
296 // For scalar variables we just make @c vecmem::edm::view remember
297 // a pointer.
298 data.template get<I>() = &(host.template get<I>());
299 } else {
300 // For 1D vectors it's enough to make @c vecmem::edm::view have a
301 // correct @c vecmem::data::vector_view object.
302 data.template get<I>() = ::vecmem::get_data(host.template get<I>());
303 }
304 // Continue the recursion.
305 get_data_impl(host, data, mr, std::index_sequence<Is...>{});
306}
307
308template <typename... VARTYPES, template <typename> class INTERFACE>
309VECMEM_HOST edm::data<edm::details::add_const_t<edm::schema<VARTYPES...>>>
311 memory_resource* resource) {
312
313 // Create the result object.
314 edm::data<edm::details::add_const_t<edm::schema<VARTYPES...>>> result;
315 // Decide what memory resource to use for setting it up.
316 memory_resource& mr = (resource != nullptr ? *resource : host.resource());
317 // Set its size, if that's available. Note that if there are no vector
318 // variables in the container, then @c vecmem::edm::data also doesn't need
319 // a memory resource.
320 if constexpr (std::disjunction_v<
322 result = {static_cast<
323 typename edm::view<edm::schema<VARTYPES...>>::size_type>(
324 host.size()),
325 mr};
326 }
327 // Fill it with the helper function.
328 get_data_impl<VARTYPES...>(host, result, mr,
329 std::index_sequence_for<VARTYPES...>{});
330 // Return the filled object.
331 return result;
332}
333
334} // namespace vecmem
An allocator class that wraps a memory resource.
Definition allocator.hpp:37
Technical base type for data<schema<VARTYPES...>>
Definition data.hpp:25
interface_type< proxy< schema_type, details::proxy_domain::host, details::proxy_access::non_constant, details::proxy_type::standalone > > object_type
Type type of standalone proxy objects for the container.
Definition host.hpp:66
std::size_t size_type
Size type used for the container.
Definition host.hpp:46
Technical base type for host<schema<VARTYPES...>,INTERFACE>
Definition host.hpp:28
Technical base type for view<schema<VARTYPES...>>
Definition view.hpp:29
Main namespace for the vecmem classes/functions.
Definition atomic_ref.hpp:16
VECMEM_HOST_AND_DEVICE constexpr const auto & get(const tuple< Ts... > &t) noexcept
Get a constant element out of a tuple.
Definition tuple.ipp:58
VECMEM_HOST void get_data_impl(edm::host< edm::schema< VARTYPES... >, INTERFACE > &, edm::data< edm::schema< VARTYPES... > > &, memory_resource &, std::index_sequence<>)
Helper function terminal node.
Definition host.ipp:197
VECMEM_HOST data::vector_view< T > get_data(array< T, N > &a)
Helper function creating a vecmem::data::vector_view object.
Definition array.ipp:217
Definition host_traits.hpp:58
Meta type describing the "schema" of an SoA container.
Definition schema.hpp:46
Definition schema_traits.hpp:108
Definition schema_traits.hpp:77
Definition schema_traits.hpp:90