VTK-m  1.8
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 
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::internal::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, const vtkm::cont::internal::Buffer* buffers) const
155  {
156  return StorageType::GetNumberOfValues(buffers);
157  }
158 };
159 
160 struct MultiplexerResizeBuffersFunctor
161 {
162  template <typename StorageType>
163  VTKM_CONT void operator()(StorageType,
164  vtkm::Id numValues,
165  vtkm::cont::internal::Buffer* buffers,
166  vtkm::CopyFlag preserve,
167  vtkm::cont::Token& token) const
168  {
169  StorageType::ResizeBuffers(numValues, buffers, preserve, token);
170  }
171 };
172 
173 struct MultiplexerFillFunctor
174 {
175  template <typename ValueType, typename StorageType>
176  VTKM_CONT void operator()(StorageType,
177  vtkm::cont::internal::Buffer* buffers,
178  const ValueType& fillValue,
179  vtkm::Id startIndex,
180  vtkm::Id endIndex,
181  vtkm::cont::Token& token) const
182  {
183  StorageType::Fill(buffers, fillValue, startIndex, endIndex, token);
184  }
185 };
186 
187 template <typename ReadPortalType>
188 struct MultiplexerCreateReadPortalFunctor
189 {
190  template <typename StorageType>
191  VTKM_CONT ReadPortalType operator()(StorageType,
192  const vtkm::cont::internal::Buffer* buffers,
194  vtkm::cont::Token& token) const
195  {
196  return ReadPortalType(StorageType::CreateReadPortal(buffers, device, token));
197  }
198 };
199 
200 template <typename WritePortalType>
201 struct MultiplexerCreateWritePortalFunctor
202 {
203  template <typename StorageType>
204  VTKM_CONT WritePortalType operator()(StorageType,
205  vtkm::cont::internal::Buffer* buffers,
207  vtkm::cont::Token& token) const
208  {
209  return WritePortalType(StorageType::CreateWritePortal(buffers, device, token));
210  }
211 };
212 
213 template <typename T, typename... Ss>
214 struct MultiplexerArrayHandleVariantFunctor
215 {
216  using VariantType = vtkm::cont::internal::Variant<vtkm::cont::ArrayHandle<T, Ss>...>;
217 
218  template <typename StorageTag>
219  VTKM_CONT VariantType operator()(vtkm::cont::internal::Storage<T, StorageTag>,
220  const vtkm::cont::internal::Buffer* buffers)
221  {
222  return VariantType(vtkm::cont::ArrayHandle<T, StorageTag>(buffers));
223  }
224 };
225 
226 } // namespace detail
227 
228 template <typename ValueType, typename... StorageTags>
229 class Storage<ValueType, StorageTagMultiplexer<StorageTags...>>
230 {
231  template <typename S>
232  using StorageFor = vtkm::cont::internal::Storage<ValueType, S>;
233 
234  using StorageVariant = vtkm::cont::internal::Variant<StorageFor<StorageTags>...>;
235 
236  VTKM_CONT static StorageVariant Variant(const vtkm::cont::internal::Buffer* buffers)
237  {
238  return buffers[0].GetMetaData<StorageVariant>();
239  }
240 
241  template <typename Buff>
242  VTKM_CONT static Buff* ArrayBuffers(Buff* buffers)
243  {
244  return buffers + 1;
245  }
246 
247 public:
248  using ReadPortalType =
249  vtkm::internal::ArrayPortalMultiplexer<typename StorageFor<StorageTags>::ReadPortalType...>;
250  using WritePortalType =
251  vtkm::internal::ArrayPortalMultiplexer<typename StorageFor<StorageTags>::WritePortalType...>;
252 
253  VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers()
254  {
255  return std::max({ StorageFor<StorageTags>::GetNumberOfBuffers()... }) + 1;
256  }
257 
258  VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
259  {
260  return Variant(buffers).CastAndCall(detail::MultiplexerGetNumberOfValuesFunctor{},
261  ArrayBuffers(buffers));
262  }
263 
264  VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
265  vtkm::cont::internal::Buffer* buffers,
266  vtkm::CopyFlag preserve,
267  vtkm::cont::Token& token)
268  {
269  Variant(buffers).CastAndCall(
270  detail::MultiplexerResizeBuffersFunctor{}, numValues, ArrayBuffers(buffers), preserve, token);
271  }
272 
273  VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
274  const ValueType& fillValue,
275  vtkm::Id startIndex,
276  vtkm::Id endIndex,
277  vtkm::cont::Token& token)
278  {
279  Variant(buffers).CastAndCall(detail::MultiplexerFillFunctor{},
280  ArrayBuffers(buffers),
281  fillValue,
282  startIndex,
283  endIndex,
284  token);
285  }
286 
287  VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
289  vtkm::cont::Token& token)
290  {
291  return Variant(buffers).CastAndCall(
292  detail::MultiplexerCreateReadPortalFunctor<ReadPortalType>{},
293  ArrayBuffers(buffers),
294  device,
295  token);
296  }
297 
298  VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
300  vtkm::cont::Token& token)
301  {
302  return Variant(buffers).CastAndCall(
303  detail::MultiplexerCreateWritePortalFunctor<WritePortalType>{},
304  ArrayBuffers(buffers),
305  device,
306  token);
307  }
308 
309  VTKM_CONT static bool IsValid(const vtkm::cont::internal::Buffer* buffers)
310  {
311  return Variant(buffers).IsValid();
312  }
313 
314  template <typename ArrayType>
315  VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const ArrayType& array)
316  {
317  VTKM_IS_ARRAY_HANDLE(ArrayType);
318  std::vector<vtkm::cont::internal::Buffer> buffers =
319  vtkm::cont::internal::CreateBuffers(StorageVariant{ array.GetStorage() }, array);
320 
321  // Some arrays will require different numbers of buffers. Make sure we size the buffers
322  // array to accomodate any such one to avoid any troubles.
323  std::size_t numBuffers = static_cast<std::size_t>(GetNumberOfBuffers());
324  VTKM_ASSERT(numBuffers >= buffers.size());
325  buffers.resize(numBuffers);
326 
327  return buffers;
328  }
329 
330  VTKM_CONT static
331  typename detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>::VariantType
332  GetArrayHandleVariant(const vtkm::cont::internal::Buffer* buffers)
333  {
334  return Variant(buffers).CastAndCall(
335  detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>{},
336  ArrayBuffers(buffers));
337  }
338 };
339 
340 } // namespace internal
341 
342 namespace detail
343 {
344 
345 template <typename... ArrayHandleTypes>
346 struct ArrayHandleMultiplexerTraits
347 {
348  using ArrayHandleType0 = vtkm::ListAt<vtkm::List<ArrayHandleTypes...>, 0>;
349  VTKM_IS_ARRAY_HANDLE(ArrayHandleType0);
350  using ValueType = typename ArrayHandleType0::ValueType;
351 
352  // If there is a compile error in this group of lines, then one of the array types given to
353  // ArrayHandleMultiplexer must contain an invalid ArrayHandle. That could mean that it is not an
354  // ArrayHandle type or it could mean that the value type does not match the appropriate value
355  // type.
356  template <typename ArrayHandle>
357  struct CheckArrayHandleTransform
358  {
359  VTKM_IS_ARRAY_HANDLE(ArrayHandle);
360  VTKM_STATIC_ASSERT((std::is_same<ValueType, typename ArrayHandle::ValueType>::value));
361  };
362  using CheckArrayHandle = vtkm::List<CheckArrayHandleTransform<ArrayHandleTypes>...>;
363 
364  // Note that this group of code could be simplified as the pair of lines:
365  // template <typename ArrayHandle>
366  // using ArrayHandleToStorageTag = typename ArrayHandle::StorageTag;
367  // However, there are issues with older Visual Studio compilers that is not working
368  // correctly with that form.
369  template <typename ArrayHandle>
370  struct ArrayHandleToStorageTagImpl
371  {
372  using Type = typename ArrayHandle::StorageTag;
373  };
374  template <typename ArrayHandle>
375  using ArrayHandleToStorageTag = typename ArrayHandleToStorageTagImpl<ArrayHandle>::Type;
376 
377  using StorageTag =
379  using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
380 };
381 } // namespace detail
382 
402 template <typename... ArrayHandleTypes>
404  : public vtkm::cont::ArrayHandle<
405  typename detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>::ValueType,
406  typename detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>::StorageTag>
407 {
408  using Traits = detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>;
409 
410 public:
415 
416 private:
417  using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
418 
419 public:
420  template <typename RealStorageTag>
422  : Superclass(StorageType::CreateBuffers(src))
423  {
424  }
425 
426  VTKM_CONT bool IsValid() const { return StorageType::IsValid(this->GetBuffers()); }
427 
428  template <typename S>
430  {
431  this->SetBuffers(StorageType::CreateBuffers(src));
432  }
433 
435  -> decltype(StorageType::GetArrayHandleVariant(this->GetBuffers()))
436  {
437  return StorageType::GetArrayHandleVariant(this->GetBuffers());
438  }
439 };
440 
449 template <typename ListTag>
450 using ArrayHandleMultiplexerFromListTag VTKM_DEPRECATED(
451  1.6,
452  "vtkm::ListTag is no longer supported. Use vtkm::List instead.") =
454 
461 template <typename List>
463 
464 namespace internal
465 {
466 
467 namespace detail
468 {
469 
470 struct ArrayExtractComponentMultiplexerFunctor
471 {
472  template <typename ArrayType>
473  auto operator()(const ArrayType& array,
474  vtkm::IdComponent componentIndex,
475  vtkm::CopyFlag allowCopy) const
476  -> decltype(vtkm::cont::ArrayExtractComponent(array, componentIndex, allowCopy))
477  {
478  return vtkm::cont::internal::ArrayExtractComponentImpl<typename ArrayType::StorageTag>{}(
479  array, componentIndex, allowCopy);
480  }
481 };
482 
483 } // namespace detail
484 
485 template <typename... Ss>
486 struct ArrayExtractComponentImpl<vtkm::cont::StorageTagMultiplexer<Ss...>>
487 {
488  template <typename T>
491  vtkm::IdComponent componentIndex,
492  vtkm::CopyFlag allowCopy)
493  {
495  return array.GetArrayHandleVariant().CastAndCall(
496  detail::ArrayExtractComponentMultiplexerFunctor{}, componentIndex, allowCopy);
497  }
498 };
499 
500 } // namespace internal
501 
502 } // namespace cont
503 
504 } // namespace vtkm
505 
506 #endif //vtk_m_cont_ArrayHandleMultiplexer_h
vtkm::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:287
ArrayHandle.h
vtkm::cont::VTKM_DEPRECATED
struct VTKM_DEPRECATED(1.6, "Use vtkm::ColorSpace.") ColorSpace
Definition: cont/ColorTable.h:36
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
Variant.h
vtkm
VTKM_NO_DEPRECATED_VIRTUAL.
Definition: Algorithms.h:18
ArrayHandleCast.h
vtkm::cont::ArrayHandleMultiplexer::IsValid
VTKM_CONT bool IsValid() const
Definition: ArrayHandleMultiplexer.h:426
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::cont::ArrayHandleMultiplexer
An ArrayHandle that can behave like several other handles.
Definition: ArrayHandleMultiplexer.h:403
Assert.h
Variant.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::ArrayHandleMultiplexer::GetArrayHandleVariant
VTKM_CONT auto GetArrayHandleVariant() const -> decltype(StorageType::GetArrayHandleVariant(this->GetBuffers()))
Definition: ArrayHandleMultiplexer.h:434
vtkm::cont::ArrayHandleStride
An ArrayHandle that accesses a basic array with strides and offsets.
Definition: ArrayHandleStride.h:249
vtkm::cont::ArrayHandleMultiplexer< vtkm::cont::ArrayHandle< vtkm::Id >, vtkm::cont::ArrayHandleIndex >::Traits
detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... > Traits
Definition: ArrayHandleMultiplexer.h:408
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::ListApply
typename detail::ListApplyImpl< internal::AsList< List >, Target >::type ListApply
Applies the list of types to a template.
Definition: List.h:159
vtkm::cont::ArrayHandleMultiplexer::ArrayHandleMultiplexer
VTKM_CONT ArrayHandleMultiplexer(const vtkm::cont::ArrayHandle< ValueType, RealStorageTag > &src)
Definition: ArrayHandleMultiplexer.h:421
VTKM_IS_ARRAY_HANDLE
#define VTKM_IS_ARRAY_HANDLE(T)
Definition: ArrayHandle.h:133
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:462
vtkm::cont::ArrayHandle< detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::ValueType, detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::StorageTag >::SetBuffers
VTKM_CONT void SetBuffers(const BufferContainer &buffers)
Definition: ArrayHandle.h:794
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:429
vtkm::ListAt
typename detail::ListAtImpl< internal::AsList< List >, Index >::type ListAt
Finds the type at the given index.
Definition: List.h:371
vtkm::cont::ArrayHandle::StorageTag
StorageTag_ StorageTag
Definition: ArrayHandle.h:295
vtkm::cont::ArrayHandle< detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::ValueType, detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::StorageTag >::StorageType
vtkm::cont::internal::Storage< ValueType, StorageTag > StorageType
Definition: ArrayHandle.h:296
vtkm::List
Definition: List.h:32
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