VTK-m  2.2
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 MultiplexerGetNumberOfComponentsFlatFunctor
152 {
153  template <typename StorageType>
154  VTKM_CONT vtkm::IdComponent operator()(
155  StorageType,
156  const std::vector<vtkm::cont::internal::Buffer>& buffers) const
157  {
158  return StorageType::GetNumberOfComponentsFlat(buffers);
159  }
160 };
161 
162 struct MultiplexerGetNumberOfValuesFunctor
163 {
164  template <typename StorageType>
165  VTKM_CONT vtkm::Id operator()(StorageType,
166  const std::vector<vtkm::cont::internal::Buffer>& buffers) const
167  {
168  return StorageType::GetNumberOfValues(buffers);
169  }
170 };
171 
172 struct MultiplexerResizeBuffersFunctor
173 {
174  template <typename StorageType>
175  VTKM_CONT void operator()(StorageType,
176  vtkm::Id numValues,
177  const std::vector<vtkm::cont::internal::Buffer>& buffers,
178  vtkm::CopyFlag preserve,
179  vtkm::cont::Token& token) const
180  {
181  StorageType::ResizeBuffers(numValues, buffers, preserve, token);
182  }
183 };
184 
185 struct MultiplexerFillFunctor
186 {
187  template <typename ValueType, typename StorageType>
188  VTKM_CONT void operator()(StorageType,
189  const std::vector<vtkm::cont::internal::Buffer>& buffers,
190  const ValueType& fillValue,
191  vtkm::Id startIndex,
192  vtkm::Id endIndex,
193  vtkm::cont::Token& token) const
194  {
195  StorageType::Fill(buffers, fillValue, startIndex, endIndex, token);
196  }
197 };
198 
199 template <typename ReadPortalType>
200 struct MultiplexerCreateReadPortalFunctor
201 {
202  template <typename StorageType>
203  VTKM_CONT ReadPortalType operator()(StorageType,
204  const std::vector<vtkm::cont::internal::Buffer>& buffers,
206  vtkm::cont::Token& token) const
207  {
208  return ReadPortalType(StorageType::CreateReadPortal(buffers, device, token));
209  }
210 };
211 
212 template <typename WritePortalType>
213 struct MultiplexerCreateWritePortalFunctor
214 {
215  template <typename StorageType>
216  VTKM_CONT WritePortalType operator()(StorageType,
217  const std::vector<vtkm::cont::internal::Buffer>& buffers,
219  vtkm::cont::Token& token) const
220  {
221  return WritePortalType(StorageType::CreateWritePortal(buffers, device, token));
222  }
223 };
224 
225 template <typename T, typename... Ss>
226 struct MultiplexerArrayHandleVariantFunctor
227 {
228  using VariantType = vtkm::cont::Variant<vtkm::cont::ArrayHandle<T, Ss>...>;
229 
230  template <typename StorageTag>
231  VTKM_CONT VariantType operator()(vtkm::cont::internal::Storage<T, StorageTag>,
232  const std::vector<vtkm::cont::internal::Buffer>& buffers)
233  {
234  return VariantType(vtkm::cont::ArrayHandle<T, StorageTag>(buffers));
235  }
236 };
237 
238 } // namespace detail
239 
240 template <typename ValueType, typename... StorageTags>
241 class Storage<ValueType, StorageTagMultiplexer<StorageTags...>>
242 {
243  template <typename S>
244  using StorageFor = vtkm::cont::internal::Storage<ValueType, S>;
245 
246  using StorageVariant = vtkm::cont::Variant<StorageFor<StorageTags>...>;
247 
248  VTKM_CONT static StorageVariant Variant(const std::vector<vtkm::cont::internal::Buffer>& buffers)
249  {
250  return buffers[0].GetMetaData<StorageVariant>();
251  }
252 
253  VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> ArrayBuffers(
254  const std::vector<vtkm::cont::internal::Buffer>& buffers)
255  {
256  return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
257  }
258 
259 public:
260  using ReadPortalType =
261  vtkm::internal::ArrayPortalMultiplexer<typename StorageFor<StorageTags>::ReadPortalType...>;
262  using WritePortalType =
263  vtkm::internal::ArrayPortalMultiplexer<typename StorageFor<StorageTags>::WritePortalType...>;
264 
265  VTKM_CONT static vtkm::IdComponent GetNumberOfComponentsFlat(
266  const std::vector<vtkm::cont::internal::Buffer>& buffers)
267  {
268  return Variant(buffers).CastAndCall(detail::MultiplexerGetNumberOfComponentsFlatFunctor{},
269  ArrayBuffers(buffers));
270  }
271 
272  VTKM_CONT static vtkm::Id GetNumberOfValues(
273  const std::vector<vtkm::cont::internal::Buffer>& buffers)
274  {
275  return Variant(buffers).CastAndCall(detail::MultiplexerGetNumberOfValuesFunctor{},
276  ArrayBuffers(buffers));
277  }
278 
279  VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
280  const std::vector<vtkm::cont::internal::Buffer>& buffers,
281  vtkm::CopyFlag preserve,
282  vtkm::cont::Token& token)
283  {
284  Variant(buffers).CastAndCall(
285  detail::MultiplexerResizeBuffersFunctor{}, numValues, ArrayBuffers(buffers), preserve, token);
286  }
287 
288  VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
289  const ValueType& fillValue,
290  vtkm::Id startIndex,
291  vtkm::Id endIndex,
292  vtkm::cont::Token& token)
293  {
294  Variant(buffers).CastAndCall(detail::MultiplexerFillFunctor{},
295  ArrayBuffers(buffers),
296  fillValue,
297  startIndex,
298  endIndex,
299  token);
300  }
301 
302  VTKM_CONT static ReadPortalType CreateReadPortal(
303  const std::vector<vtkm::cont::internal::Buffer>& buffers,
305  vtkm::cont::Token& token)
306  {
307  return Variant(buffers).CastAndCall(
308  detail::MultiplexerCreateReadPortalFunctor<ReadPortalType>{},
309  ArrayBuffers(buffers),
310  device,
311  token);
312  }
313 
314  VTKM_CONT static WritePortalType CreateWritePortal(
315  const std::vector<vtkm::cont::internal::Buffer>& buffers,
317  vtkm::cont::Token& token)
318  {
319  return Variant(buffers).CastAndCall(
320  detail::MultiplexerCreateWritePortalFunctor<WritePortalType>{},
321  ArrayBuffers(buffers),
322  device,
323  token);
324  }
325 
326  VTKM_CONT static bool IsValid(const std::vector<vtkm::cont::internal::Buffer>& buffers)
327  {
328  return Variant(buffers).IsValid();
329  }
330 
331  template <typename ArrayType>
332  VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const ArrayType& array)
333  {
334  VTKM_IS_ARRAY_HANDLE(ArrayType);
335  return vtkm::cont::internal::CreateBuffers(StorageVariant{ array.GetStorage() }, array);
336  }
337 
338  VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
339  {
340  return vtkm::cont::internal::CreateBuffers(StorageVariant{});
341  }
342 
343  VTKM_CONT static
344  typename detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>::VariantType
345  GetArrayHandleVariant(const std::vector<vtkm::cont::internal::Buffer>& buffers)
346  {
347  return Variant(buffers).CastAndCall(
348  detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>{},
349  ArrayBuffers(buffers));
350  }
351 };
352 
353 } // namespace internal
354 
355 namespace detail
356 {
357 
358 template <typename... ArrayHandleTypes>
359 struct ArrayHandleMultiplexerTraits
360 {
361  using ArrayHandleType0 = vtkm::ListAt<vtkm::List<ArrayHandleTypes...>, 0>;
362  VTKM_IS_ARRAY_HANDLE(ArrayHandleType0);
363  using ValueType = typename ArrayHandleType0::ValueType;
364 
365  // If there is a compile error in this group of lines, then one of the array types given to
366  // ArrayHandleMultiplexer must contain an invalid ArrayHandle. That could mean that it is not an
367  // ArrayHandle type or it could mean that the value type does not match the appropriate value
368  // type.
369  template <typename ArrayHandle>
370  struct CheckArrayHandleTransform
371  {
372  VTKM_IS_ARRAY_HANDLE(ArrayHandle);
373  VTKM_STATIC_ASSERT((std::is_same<ValueType, typename ArrayHandle::ValueType>::value));
374  };
375  using CheckArrayHandle = vtkm::List<CheckArrayHandleTransform<ArrayHandleTypes>...>;
376 
377  // Note that this group of code could be simplified as the pair of lines:
378  // template <typename ArrayHandle>
379  // using ArrayHandleToStorageTag = typename ArrayHandle::StorageTag;
380  // However, there are issues with older Visual Studio compilers that is not working
381  // correctly with that form.
382  template <typename ArrayHandle>
383  struct ArrayHandleToStorageTagImpl
384  {
385  using Type = typename ArrayHandle::StorageTag;
386  };
387  template <typename ArrayHandle>
388  using ArrayHandleToStorageTag = typename ArrayHandleToStorageTagImpl<ArrayHandle>::Type;
389 
390  using StorageTag =
392  using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
393 };
394 } // namespace detail
395 
415 template <typename... ArrayHandleTypes>
417  : public vtkm::cont::ArrayHandle<
418  typename detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>::ValueType,
419  typename detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>::StorageTag>
420 {
421  using Traits = detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>;
422 
423 public:
428 
429  template <typename RealStorageTag>
431  : Superclass(StorageType::CreateBuffers(src))
432  {
433  }
434 
435  VTKM_CONT bool IsValid() const { return StorageType::IsValid(this->GetBuffers()); }
436 
437  template <typename S>
439  {
440  this->SetBuffers(StorageType::CreateBuffers(src));
441  }
442 
444  -> decltype(StorageType::GetArrayHandleVariant(this->GetBuffers()))
445  {
446  return StorageType::GetArrayHandleVariant(this->GetBuffers());
447  }
448 };
449 
456 template <typename List>
458 
459 namespace internal
460 {
461 
462 namespace detail
463 {
464 
465 struct ArrayExtractComponentMultiplexerFunctor
466 {
467  template <typename ArrayType>
468  auto operator()(const ArrayType& array,
469  vtkm::IdComponent componentIndex,
470  vtkm::CopyFlag allowCopy) const
471  -> decltype(vtkm::cont::ArrayExtractComponent(array, componentIndex, allowCopy))
472  {
473  return vtkm::cont::internal::ArrayExtractComponentImpl<typename ArrayType::StorageTag>{}(
474  array, componentIndex, allowCopy);
475  }
476 };
477 
478 } // namespace detail
479 
480 template <typename... Ss>
481 struct ArrayExtractComponentImpl<vtkm::cont::StorageTagMultiplexer<Ss...>>
482 {
483  template <typename T>
486  vtkm::IdComponent componentIndex,
487  vtkm::CopyFlag allowCopy)
488  {
490  return array.GetArrayHandleVariant().CastAndCall(
491  detail::ArrayExtractComponentMultiplexerFunctor{}, componentIndex, allowCopy);
492  }
493 };
494 
495 } // namespace internal
496 
497 } // namespace cont
498 
499 } // namespace vtkm
500 
501 #endif //vtk_m_cont_ArrayHandleMultiplexer_h
vtkm::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:300
ArrayHandle.h
ArrayExtractComponent.h
vtkm::cont::ArrayExtractComponent
vtkm::cont::ArrayHandleStride< typename vtkm::VecTraits< 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:255
vtkm::cont::ArrayHandle< detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::ValueType, detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::StorageTag >::GetBuffers
const std::vector< vtkm::cont::internal::Buffer > & GetBuffers() const
Returns the internal Buffer structures that hold the data.
Definition: ArrayHandle.h:721
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::Get
auto Get(const vtkm::Tuple< Ts... > &tuple)
Retrieve the object from a vtkm::Tuple at the given index.
Definition: Tuple.h:81
VTKM_ARRAY_HANDLE_SUBCLASS
#define VTKM_ARRAY_HANDLE_SUBCLASS(classname, fullclasstype, superclass)
Macro to make default methods in ArrayHandle subclasses.
Definition: ArrayHandle.h:243
ArrayHandleCast.h
VTKM_ASSERT
#define VTKM_ASSERT(condition)
Definition: Assert.h:43
VTKM_EXEC_CONT
#define VTKM_EXEC_CONT
Definition: ExportMacros.h:52
vtkm::IdComponent
vtkm::Int32 IdComponent
Base type to use to index small lists.
Definition: Types.h:194
vtkm::ListApply
typename detail::ListApplyImpl< List, Target >::type ListApply
Applies the list of types to a template.
Definition: List.h:138
Variant.h
Variant.h
vtkm::cont::ArrayHandleMultiplexer
An ArrayHandle that can behave like several other handles.
Definition: ArrayHandleMultiplexer.h:416
Assert.h
vtkm::cont::ArrayHandleMultiplexer::GetArrayHandleVariant
auto GetArrayHandleVariant() const -> decltype(StorageType::GetArrayHandleVariant(this->GetBuffers()))
Definition: ArrayHandleMultiplexer.h:443
vtkm::ListAt
typename detail::ListAtImpl< List, Index >::type ListAt
Finds the type at the given index.
Definition: List.h:350
vtkm::cont::ArrayHandleStride
An ArrayHandle that accesses a basic array with strides and offsets.
Definition: ArrayHandleStride.h:332
vtkm::cont::ArrayHandleMultiplexer::Traits
detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... > Traits
Definition: ArrayHandleMultiplexer.h:421
vtkm::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:35
vtkm::cont::ArrayHandleMultiplexer::IsValid
bool IsValid() const
Definition: ArrayHandleMultiplexer.h:435
TypeTraits.h
ArrayHandleUniformPointCoordinates.h
vtkm::cont::ArrayHandle< detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::ValueType, detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::StorageTag >::SetBuffers
void SetBuffers(const std::vector< vtkm::cont::internal::Buffer > &buffers)
Definition: ArrayHandle.h:736
VTKM_STATIC_ASSERT
#define VTKM_STATIC_ASSERT(condition)
Definition: StaticAssert.h:16
vtkm::cont::ArrayHandleMultiplexer::ArrayHandleMultiplexer
ArrayHandleMultiplexer(const vtkm::cont::ArrayHandle< ValueType, RealStorageTag > &src)
Definition: ArrayHandleMultiplexer.h:430
VTKM_IS_ARRAY_HANDLE
#define VTKM_IS_ARRAY_HANDLE(T)
Checks that the given type is a vtkm::cont::ArrayHandle.
Definition: ArrayHandle.h:137
vtkm::cont::ArrayHandleMultiplexer::StorageType
typename Superclass::StorageType StorageType
Definition: ArrayHandleMultiplexer.h:427
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:457
vtkm::Id
vtkm::Int64 Id
Base type to use to index arrays.
Definition: Types.h:227
vtkm::cont::DeviceAdapterId
An object used to specify a device.
Definition: DeviceAdapterTag.h:58
vtkm::cont::ArrayHandle::StorageTag
StorageTag_ StorageTag
Definition: ArrayHandle.h:308
vtkm::List
A template used to hold a list of types.
Definition: List.h:39
vtkm::CopyFlag
CopyFlag
Identifier used to specify whether a function should deep copy data.
Definition: Flags.h:17
vtkm::cont::ArrayHandleMultiplexer::SetArray
void SetArray(const vtkm::cont::ArrayHandle< ValueType, S > &src)
Definition: ArrayHandleMultiplexer.h:438
vtkm::cont::ArrayHandleMultiplexer::Superclass
typename vtkm::cont::detail::GetTypeInParentheses< void(vtkm::cont::ArrayHandle< typename Traits::ValueType, typename Traits::StorageTag >) >::type Superclass
Definition: ArrayHandleMultiplexer.h:427
VTKM_SUPPRESS_EXEC_WARNINGS
#define VTKM_SUPPRESS_EXEC_WARNINGS
Definition: ExportMacros.h:53
vtkm::cont::StorageTagMultiplexer
Definition: ArrayHandleMultiplexer.h:141