VTK-m  2.0
ArrayHandleMultiplexer.h
Go to the documentation of this file.
1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //============================================================================
10 #ifndef vtk_m_cont_ArrayHandleMultiplexer_h
11 #define vtk_m_cont_ArrayHandleMultiplexer_h
12 
13 #include <vtkm/Assert.h>
14 #include <vtkm/TypeTraits.h>
15 
17 #include <vtkm/cont/ArrayHandle.h>
21 
22 #include <vtkm/cont/Variant.h>
23 #include <vtkm/exec/Variant.h>
24 
25 namespace vtkm
26 {
27 
28 namespace internal
29 {
30 
31 namespace detail
32 {
33 
34 struct ArrayPortalMultiplexerGetNumberOfValuesFunctor
35 {
36  template <typename PortalType>
37  VTKM_EXEC_CONT vtkm::Id operator()(const PortalType& portal) const noexcept
38  {
39  return portal.GetNumberOfValues();
40  }
41 };
42 
43 struct ArrayPortalMultiplexerGetFunctor
44 {
46  template <typename PortalType>
47  VTKM_EXEC_CONT typename PortalType::ValueType operator()(const PortalType& portal,
48  vtkm::Id index) const noexcept
49  {
50  return portal.Get(index);
51  }
52 };
53 
54 struct ArrayPortalMultiplexerSetFunctor
55 {
56  template <typename PortalType>
57  VTKM_EXEC_CONT void operator()(const PortalType& portal,
58  vtkm::Id index,
59  const typename PortalType::ValueType& value) const noexcept
60  {
61  this->DoSet(
62  portal, index, value, typename vtkm::internal::PortalSupportsSets<PortalType>::type{});
63  }
64 
65 private:
67  template <typename PortalType>
68  VTKM_EXEC_CONT void DoSet(const PortalType& portal,
69  vtkm::Id index,
70  const typename PortalType::ValueType& value,
71  std::true_type) const noexcept
72  {
73  portal.Set(index, value);
74  }
75 
77  template <typename PortalType>
78  VTKM_EXEC_CONT void DoSet(const PortalType&,
79  vtkm::Id,
80  const typename PortalType::ValueType&,
81  std::false_type) const noexcept
82  {
83  // This is an error but whatever.
84  VTKM_ASSERT(false && "Calling Set on a portal that does not support it.");
85  }
86 };
87 
88 } // namespace detail
89 
90 template <typename... PortalTypes>
91 struct ArrayPortalMultiplexer
92 {
93  using PortalVariantType = vtkm::exec::Variant<PortalTypes...>;
94  PortalVariantType PortalVariant;
95 
96  using ValueType = typename PortalVariantType::template TypeAt<0>::ValueType;
97 
98  ArrayPortalMultiplexer() = default;
99  ~ArrayPortalMultiplexer() = default;
100  ArrayPortalMultiplexer(ArrayPortalMultiplexer&&) = default;
101  ArrayPortalMultiplexer(const ArrayPortalMultiplexer&) = default;
102  ArrayPortalMultiplexer& operator=(ArrayPortalMultiplexer&&) = default;
103  ArrayPortalMultiplexer& operator=(const ArrayPortalMultiplexer&) = default;
104 
105  template <typename Portal>
106  VTKM_EXEC_CONT ArrayPortalMultiplexer(const Portal& src) noexcept
107  : PortalVariant(src)
108  {
109  }
110 
111  template <typename Portal>
112  VTKM_EXEC_CONT ArrayPortalMultiplexer& operator=(const Portal& src) noexcept
113  {
114  this->PortalVariant = src;
115  return *this;
116  }
117 
118  VTKM_EXEC_CONT vtkm::Id GetNumberOfValues() const noexcept
119  {
120  return this->PortalVariant.CastAndCall(
121  detail::ArrayPortalMultiplexerGetNumberOfValuesFunctor{});
122  }
123 
124  VTKM_EXEC_CONT ValueType Get(vtkm::Id index) const noexcept
125  {
126  return this->PortalVariant.CastAndCall(detail::ArrayPortalMultiplexerGetFunctor{}, index);
127  }
128 
129  VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const noexcept
130  {
131  this->PortalVariant.CastAndCall(detail::ArrayPortalMultiplexerSetFunctor{}, index, value);
132  }
133 };
134 
135 } // namespace internal
136 
137 namespace cont
138 {
139 
140 template <typename... StorageTags>
142 {
143 };
144 
145 namespace internal
146 {
147 
148 namespace detail
149 {
150 
151 struct MultiplexerGetNumberOfValuesFunctor
152 {
153  template <typename StorageType>
154  VTKM_CONT vtkm::Id operator()(StorageType,
155  const std::vector<vtkm::cont::internal::Buffer>& buffers) const
156  {
157  return StorageType::GetNumberOfValues(buffers);
158  }
159 };
160 
161 struct MultiplexerResizeBuffersFunctor
162 {
163  template <typename StorageType>
164  VTKM_CONT void operator()(StorageType,
165  vtkm::Id numValues,
166  const std::vector<vtkm::cont::internal::Buffer>& buffers,
167  vtkm::CopyFlag preserve,
168  vtkm::cont::Token& token) const
169  {
170  StorageType::ResizeBuffers(numValues, buffers, preserve, token);
171  }
172 };
173 
174 struct MultiplexerFillFunctor
175 {
176  template <typename ValueType, typename StorageType>
177  VTKM_CONT void operator()(StorageType,
178  const std::vector<vtkm::cont::internal::Buffer>& buffers,
179  const ValueType& fillValue,
180  vtkm::Id startIndex,
181  vtkm::Id endIndex,
182  vtkm::cont::Token& token) const
183  {
184  StorageType::Fill(buffers, fillValue, startIndex, endIndex, token);
185  }
186 };
187 
188 template <typename ReadPortalType>
189 struct MultiplexerCreateReadPortalFunctor
190 {
191  template <typename StorageType>
192  VTKM_CONT ReadPortalType operator()(StorageType,
193  const std::vector<vtkm::cont::internal::Buffer>& buffers,
195  vtkm::cont::Token& token) const
196  {
197  return ReadPortalType(StorageType::CreateReadPortal(buffers, device, token));
198  }
199 };
200 
201 template <typename WritePortalType>
202 struct MultiplexerCreateWritePortalFunctor
203 {
204  template <typename StorageType>
205  VTKM_CONT WritePortalType operator()(StorageType,
206  const std::vector<vtkm::cont::internal::Buffer>& buffers,
208  vtkm::cont::Token& token) const
209  {
210  return WritePortalType(StorageType::CreateWritePortal(buffers, device, token));
211  }
212 };
213 
214 template <typename T, typename... Ss>
215 struct MultiplexerArrayHandleVariantFunctor
216 {
217  using VariantType = vtkm::cont::Variant<vtkm::cont::ArrayHandle<T, Ss>...>;
218 
219  template <typename StorageTag>
220  VTKM_CONT VariantType operator()(vtkm::cont::internal::Storage<T, StorageTag>,
221  const std::vector<vtkm::cont::internal::Buffer>& buffers)
222  {
223  return VariantType(vtkm::cont::ArrayHandle<T, StorageTag>(buffers));
224  }
225 };
226 
227 } // namespace detail
228 
229 template <typename ValueType, typename... StorageTags>
230 class Storage<ValueType, StorageTagMultiplexer<StorageTags...>>
231 {
232  template <typename S>
233  using StorageFor = vtkm::cont::internal::Storage<ValueType, S>;
234 
235  using StorageVariant = vtkm::cont::Variant<StorageFor<StorageTags>...>;
236 
237  VTKM_CONT static StorageVariant Variant(const std::vector<vtkm::cont::internal::Buffer>& buffers)
238  {
239  return buffers[0].GetMetaData<StorageVariant>();
240  }
241 
242  VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> ArrayBuffers(
243  const std::vector<vtkm::cont::internal::Buffer>& buffers)
244  {
245  return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
246  }
247 
248 public:
249  using ReadPortalType =
250  vtkm::internal::ArrayPortalMultiplexer<typename StorageFor<StorageTags>::ReadPortalType...>;
251  using WritePortalType =
252  vtkm::internal::ArrayPortalMultiplexer<typename StorageFor<StorageTags>::WritePortalType...>;
253 
254  VTKM_CONT static vtkm::Id GetNumberOfValues(
255  const std::vector<vtkm::cont::internal::Buffer>& buffers)
256  {
257  return Variant(buffers).CastAndCall(detail::MultiplexerGetNumberOfValuesFunctor{},
258  ArrayBuffers(buffers));
259  }
260 
261  VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
262  const std::vector<vtkm::cont::internal::Buffer>& buffers,
263  vtkm::CopyFlag preserve,
264  vtkm::cont::Token& token)
265  {
266  Variant(buffers).CastAndCall(
267  detail::MultiplexerResizeBuffersFunctor{}, numValues, ArrayBuffers(buffers), preserve, token);
268  }
269 
270  VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
271  const ValueType& fillValue,
272  vtkm::Id startIndex,
273  vtkm::Id endIndex,
274  vtkm::cont::Token& token)
275  {
276  Variant(buffers).CastAndCall(detail::MultiplexerFillFunctor{},
277  ArrayBuffers(buffers),
278  fillValue,
279  startIndex,
280  endIndex,
281  token);
282  }
283 
284  VTKM_CONT static ReadPortalType CreateReadPortal(
285  const std::vector<vtkm::cont::internal::Buffer>& buffers,
287  vtkm::cont::Token& token)
288  {
289  return Variant(buffers).CastAndCall(
290  detail::MultiplexerCreateReadPortalFunctor<ReadPortalType>{},
291  ArrayBuffers(buffers),
292  device,
293  token);
294  }
295 
296  VTKM_CONT static WritePortalType CreateWritePortal(
297  const std::vector<vtkm::cont::internal::Buffer>& buffers,
299  vtkm::cont::Token& token)
300  {
301  return Variant(buffers).CastAndCall(
302  detail::MultiplexerCreateWritePortalFunctor<WritePortalType>{},
303  ArrayBuffers(buffers),
304  device,
305  token);
306  }
307 
308  VTKM_CONT static bool IsValid(const std::vector<vtkm::cont::internal::Buffer>& buffers)
309  {
310  return Variant(buffers).IsValid();
311  }
312 
313  template <typename ArrayType>
314  VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const ArrayType& array)
315  {
316  VTKM_IS_ARRAY_HANDLE(ArrayType);
317  return vtkm::cont::internal::CreateBuffers(StorageVariant{ array.GetStorage() }, array);
318  }
319 
320  VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
321  {
322  return vtkm::cont::internal::CreateBuffers(StorageVariant{});
323  }
324 
325  VTKM_CONT static
326  typename detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>::VariantType
327  GetArrayHandleVariant(const std::vector<vtkm::cont::internal::Buffer>& buffers)
328  {
329  return Variant(buffers).CastAndCall(
330  detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>{},
331  ArrayBuffers(buffers));
332  }
333 };
334 
335 } // namespace internal
336 
337 namespace detail
338 {
339 
340 template <typename... ArrayHandleTypes>
341 struct ArrayHandleMultiplexerTraits
342 {
343  using ArrayHandleType0 = vtkm::ListAt<vtkm::List<ArrayHandleTypes...>, 0>;
344  VTKM_IS_ARRAY_HANDLE(ArrayHandleType0);
345  using ValueType = typename ArrayHandleType0::ValueType;
346 
347  // If there is a compile error in this group of lines, then one of the array types given to
348  // ArrayHandleMultiplexer must contain an invalid ArrayHandle. That could mean that it is not an
349  // ArrayHandle type or it could mean that the value type does not match the appropriate value
350  // type.
351  template <typename ArrayHandle>
352  struct CheckArrayHandleTransform
353  {
354  VTKM_IS_ARRAY_HANDLE(ArrayHandle);
355  VTKM_STATIC_ASSERT((std::is_same<ValueType, typename ArrayHandle::ValueType>::value));
356  };
357  using CheckArrayHandle = vtkm::List<CheckArrayHandleTransform<ArrayHandleTypes>...>;
358 
359  // Note that this group of code could be simplified as the pair of lines:
360  // template <typename ArrayHandle>
361  // using ArrayHandleToStorageTag = typename ArrayHandle::StorageTag;
362  // However, there are issues with older Visual Studio compilers that is not working
363  // correctly with that form.
364  template <typename ArrayHandle>
365  struct ArrayHandleToStorageTagImpl
366  {
367  using Type = typename ArrayHandle::StorageTag;
368  };
369  template <typename ArrayHandle>
370  using ArrayHandleToStorageTag = typename ArrayHandleToStorageTagImpl<ArrayHandle>::Type;
371 
372  using StorageTag =
374  using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
375 };
376 } // namespace detail
377 
397 template <typename... ArrayHandleTypes>
399  : public vtkm::cont::ArrayHandle<
400  typename detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>::ValueType,
401  typename detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>::StorageTag>
402 {
403  using Traits = detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>;
404 
405 public:
410 
411 private:
412  using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
413 
414 public:
415  template <typename RealStorageTag>
417  : Superclass(StorageType::CreateBuffers(src))
418  {
419  }
420 
421  VTKM_CONT bool IsValid() const { return StorageType::IsValid(this->GetBuffers()); }
422 
423  template <typename S>
425  {
426  this->SetBuffers(StorageType::CreateBuffers(src));
427  }
428 
430  -> decltype(StorageType::GetArrayHandleVariant(this->GetBuffers()))
431  {
432  return StorageType::GetArrayHandleVariant(this->GetBuffers());
433  }
434 };
435 
442 template <typename List>
444 
445 namespace internal
446 {
447 
448 namespace detail
449 {
450 
451 struct ArrayExtractComponentMultiplexerFunctor
452 {
453  template <typename ArrayType>
454  auto operator()(const ArrayType& array,
455  vtkm::IdComponent componentIndex,
456  vtkm::CopyFlag allowCopy) const
457  -> decltype(vtkm::cont::ArrayExtractComponent(array, componentIndex, allowCopy))
458  {
459  return vtkm::cont::internal::ArrayExtractComponentImpl<typename ArrayType::StorageTag>{}(
460  array, componentIndex, allowCopy);
461  }
462 };
463 
464 } // namespace detail
465 
466 template <typename... Ss>
467 struct ArrayExtractComponentImpl<vtkm::cont::StorageTagMultiplexer<Ss...>>
468 {
469  template <typename T>
472  vtkm::IdComponent componentIndex,
473  vtkm::CopyFlag allowCopy)
474  {
476  return array.GetArrayHandleVariant().CastAndCall(
477  detail::ArrayExtractComponentMultiplexerFunctor{}, componentIndex, allowCopy);
478  }
479 };
480 
481 } // namespace internal
482 
483 } // namespace cont
484 
485 } // namespace vtkm
486 
487 #endif //vtk_m_cont_ArrayHandleMultiplexer_h
vtkm::cont::ArrayHandle< detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::ValueType, detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::StorageTag >::GetBuffers
const VTKM_CONT std::vector< vtkm::cont::internal::Buffer > & GetBuffers() const
Returns the internal Buffer structures that hold the data.
Definition: ArrayHandle.h:696
vtkm::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:283
ArrayHandle.h
ArrayExtractComponent.h
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
ArrayHandleCast.h
vtkm::cont::ArrayHandleMultiplexer::IsValid
VTKM_CONT bool IsValid() const
Definition: ArrayHandleMultiplexer.h:421
VTKM_ASSERT
#define VTKM_ASSERT(condition)
Definition: Assert.h:43
VTKM_EXEC_CONT
#define VTKM_EXEC_CONT
Definition: ExportMacros.h:52
vtkm::Get
VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT auto Get(const vtkm::Tuple< Ts... > &tuple) -> decltype(tuple.template Get< Index >())
Retrieve the object from a vtkm::Tuple at the given index.
Definition: Tuple.h:83
vtkm::IdComponent
vtkm::Int32 IdComponent
Represents a component ID (index of component in a vector).
Definition: Types.h:168
vtkm::ListApply
typename detail::ListApplyImpl< List, Target >::type ListApply
Applies the list of types to a template.
Definition: List.h:132
Variant.h
Variant.h
vtkm::cont::ArrayHandleMultiplexer
An ArrayHandle that can behave like several other handles.
Definition: ArrayHandleMultiplexer.h:398
Assert.h
vtkm::cont::ArrayHandleMultiplexer::VTKM_ARRAY_HANDLE_SUBCLASS
VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleMultiplexer,(ArrayHandleMultiplexer< ArrayHandleTypes... >),(vtkm::cont::ArrayHandle< typename Traits::ValueType, typename Traits::StorageTag >))
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::cont::ArrayHandle< detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::ValueType, detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::StorageTag >::SetBuffers
VTKM_CONT void SetBuffers(const std::vector< vtkm::cont::internal::Buffer > &buffers)
Definition: ArrayHandle.h:711
vtkm::cont::ArrayHandleMultiplexer::GetArrayHandleVariant
VTKM_CONT auto GetArrayHandleVariant() const -> decltype(StorageType::GetArrayHandleVariant(this->GetBuffers()))
Definition: ArrayHandleMultiplexer.h:429
vtkm::ListAt
typename detail::ListAtImpl< List, Index >::type ListAt
Finds the type at the given index.
Definition: List.h:344
vtkm::cont::ArrayHandleStride
An ArrayHandle that accesses a basic array with strides and offsets.
Definition: ArrayHandleStride.h:251
vtkm::cont::ArrayHandleMultiplexer< vtkm::cont::ArrayHandle< vtkm::Id >, vtkm::cont::ArrayHandleIndex >::Traits
detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... > Traits
Definition: ArrayHandleMultiplexer.h:403
vtkm::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:35
TypeTraits.h
ArrayHandleUniformPointCoordinates.h
VTKM_STATIC_ASSERT
#define VTKM_STATIC_ASSERT(condition)
Definition: StaticAssert.h:16
vtkm::cont::ArrayHandleMultiplexer::ArrayHandleMultiplexer
VTKM_CONT ArrayHandleMultiplexer(const vtkm::cont::ArrayHandle< ValueType, RealStorageTag > &src)
Definition: ArrayHandleMultiplexer.h:416
VTKM_IS_ARRAY_HANDLE
#define VTKM_IS_ARRAY_HANDLE(T)
Definition: ArrayHandle.h:132
ArrayHandleCartesianProduct.h
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::cont::ArrayHandleMultiplexerFromList
vtkm::ListApply< List, ArrayHandleMultiplexer > ArrayHandleMultiplexerFromList
Converts avtkm::List to an ArrayHandleMultiplexer
Definition: ArrayHandleMultiplexer.h:443
vtkm::cont::DeviceAdapterId
Definition: DeviceAdapterTag.h:52
vtkm::cont::ArrayHandleMultiplexer::SetArray
VTKM_CONT void SetArray(const vtkm::cont::ArrayHandle< ValueType, S > &src)
Definition: ArrayHandleMultiplexer.h:424
vtkm::cont::ArrayHandle::StorageTag
StorageTag_ StorageTag
Definition: ArrayHandle.h:291
vtkm::cont::ArrayHandle< detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::ValueType, detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::StorageTag >::StorageType
vtkm::cont::internal::Storage< ValueType, StorageTag > StorageType
Definition: ArrayHandle.h:292
vtkm::cont::ArrayExtractComponent
vtkm::cont::ArrayHandleStride< typename vtkm::internal::SafeVecTraits< T >::BaseComponentType > ArrayExtractComponent(const vtkm::cont::ArrayHandle< T, S > &src, vtkm::IdComponent componentIndex, vtkm::CopyFlag allowCopy=vtkm::CopyFlag::On)
Pulls a component out of an ArrayHandle.
Definition: ArrayExtractComponent.h:258
vtkm::List
Definition: List.h:34
vtkm::CopyFlag
CopyFlag
Definition: Flags.h:16
VTKM_SUPPRESS_EXEC_WARNINGS
#define VTKM_SUPPRESS_EXEC_WARNINGS
Definition: ExportMacros.h:53
vtkm::cont::StorageTagMultiplexer
Definition: ArrayHandleMultiplexer.h:141