Viskores  1.0
ArrayHandleMultiplexer.h
Go to the documentation of this file.
1 //============================================================================
2 // The contents of this file are covered by the Viskores license. See
3 // LICENSE.txt for details.
4 //
5 // By contributing to this file, all contributors agree to the Developer
6 // Certificate of Origin Version 1.1 (DCO 1.1) as stated in DCO.txt.
7 //============================================================================
8 
9 //============================================================================
10 // Copyright (c) Kitware, Inc.
11 // All rights reserved.
12 // See LICENSE.txt for details.
13 //
14 // This software is distributed WITHOUT ANY WARRANTY; without even
15 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 // PURPOSE. See the above copyright notice for more information.
17 //============================================================================
18 #ifndef viskores_cont_ArrayHandleMultiplexer_h
19 #define viskores_cont_ArrayHandleMultiplexer_h
20 
21 #include <viskores/Assert.h>
22 #include <viskores/TypeTraits.h>
23 
29 
30 #include <viskores/cont/Variant.h>
31 #include <viskores/exec/Variant.h>
32 
33 namespace viskores
34 {
35 
36 namespace internal
37 {
38 
39 namespace detail
40 {
41 
42 struct ArrayPortalMultiplexerGetNumberOfValuesFunctor
43 {
44  template <typename PortalType>
45  VISKORES_EXEC_CONT viskores::Id operator()(const PortalType& portal) const noexcept
46  {
47  return portal.GetNumberOfValues();
48  }
49 };
50 
51 struct ArrayPortalMultiplexerGetFunctor
52 {
54  template <typename PortalType>
55  VISKORES_EXEC_CONT typename PortalType::ValueType operator()(const PortalType& portal,
56  viskores::Id index) const noexcept
57  {
58  return portal.Get(index);
59  }
60 };
61 
62 struct ArrayPortalMultiplexerSetFunctor
63 {
64  template <typename PortalType>
65  VISKORES_EXEC_CONT void operator()(const PortalType& portal,
66  viskores::Id index,
67  const typename PortalType::ValueType& value) const noexcept
68  {
69  this->DoSet(
70  portal, index, value, typename viskores::internal::PortalSupportsSets<PortalType>::type{});
71  }
72 
73 private:
75  template <typename PortalType>
76  VISKORES_EXEC_CONT void DoSet(const PortalType& portal,
77  viskores::Id index,
78  const typename PortalType::ValueType& value,
79  std::true_type) const noexcept
80  {
81  portal.Set(index, value);
82  }
83 
85  template <typename PortalType>
86  VISKORES_EXEC_CONT void DoSet(const PortalType&,
88  const typename PortalType::ValueType&,
89  std::false_type) const noexcept
90  {
91  // This is an error but whatever.
92  VISKORES_ASSERT(false && "Calling Set on a portal that does not support it.");
93  }
94 };
95 
96 } // namespace detail
97 
98 template <typename... PortalTypes>
99 struct ArrayPortalMultiplexer
100 {
101  using PortalVariantType = viskores::exec::Variant<PortalTypes...>;
102  PortalVariantType PortalVariant;
103 
104  using ValueType = typename PortalVariantType::template TypeAt<0>::ValueType;
105 
106  ArrayPortalMultiplexer() = default;
107  ~ArrayPortalMultiplexer() = default;
108  ArrayPortalMultiplexer(ArrayPortalMultiplexer&&) = default;
109  ArrayPortalMultiplexer(const ArrayPortalMultiplexer&) = default;
110  ArrayPortalMultiplexer& operator=(ArrayPortalMultiplexer&&) = default;
111  ArrayPortalMultiplexer& operator=(const ArrayPortalMultiplexer&) = default;
112 
113  template <typename Portal>
114  VISKORES_EXEC_CONT ArrayPortalMultiplexer(const Portal& src) noexcept
115  : PortalVariant(src)
116  {
117  }
118 
119  template <typename Portal>
120  VISKORES_EXEC_CONT ArrayPortalMultiplexer& operator=(const Portal& src) noexcept
121  {
122  this->PortalVariant = src;
123  return *this;
124  }
125 
126  VISKORES_EXEC_CONT viskores::Id GetNumberOfValues() const noexcept
127  {
128  return this->PortalVariant.CastAndCall(
129  detail::ArrayPortalMultiplexerGetNumberOfValuesFunctor{});
130  }
131 
132  VISKORES_EXEC_CONT ValueType Get(viskores::Id index) const noexcept
133  {
134  return this->PortalVariant.CastAndCall(detail::ArrayPortalMultiplexerGetFunctor{}, index);
135  }
136 
137  VISKORES_EXEC_CONT void Set(viskores::Id index, const ValueType& value) const noexcept
138  {
139  this->PortalVariant.CastAndCall(detail::ArrayPortalMultiplexerSetFunctor{}, index, value);
140  }
141 };
142 
143 } // namespace internal
144 
145 namespace cont
146 {
147 
148 template <typename... StorageTags>
150 {
151 };
152 
153 namespace internal
154 {
155 
156 namespace detail
157 {
158 
159 struct MultiplexerGetNumberOfComponentsFlatFunctor
160 {
161  template <typename StorageType>
163  StorageType,
164  const std::vector<viskores::cont::internal::Buffer>& buffers) const
165  {
166  return StorageType::GetNumberOfComponentsFlat(buffers);
167  }
168 };
169 
170 struct MultiplexerGetNumberOfValuesFunctor
171 {
172  template <typename StorageType>
173  VISKORES_CONT viskores::Id operator()(
174  StorageType,
175  const std::vector<viskores::cont::internal::Buffer>& buffers) const
176  {
177  return StorageType::GetNumberOfValues(buffers);
178  }
179 };
180 
181 struct MultiplexerResizeBuffersFunctor
182 {
183  template <typename StorageType>
184  VISKORES_CONT void operator()(StorageType,
185  viskores::Id numValues,
186  const std::vector<viskores::cont::internal::Buffer>& buffers,
187  viskores::CopyFlag preserve,
188  viskores::cont::Token& token) const
189  {
190  StorageType::ResizeBuffers(numValues, buffers, preserve, token);
191  }
192 };
193 
194 struct MultiplexerFillFunctor
195 {
196  template <typename ValueType, typename StorageType>
197  VISKORES_CONT void operator()(StorageType,
198  const std::vector<viskores::cont::internal::Buffer>& buffers,
199  const ValueType& fillValue,
200  viskores::Id startIndex,
201  viskores::Id endIndex,
202  viskores::cont::Token& token) const
203  {
204  StorageType::Fill(buffers, fillValue, startIndex, endIndex, token);
205  }
206 };
207 
208 template <typename ReadPortalType>
209 struct MultiplexerCreateReadPortalFunctor
210 {
211  template <typename StorageType>
212  VISKORES_CONT ReadPortalType
213  operator()(StorageType,
214  const std::vector<viskores::cont::internal::Buffer>& buffers,
216  viskores::cont::Token& token) const
217  {
218  return ReadPortalType(StorageType::CreateReadPortal(buffers, device, token));
219  }
220 };
221 
222 template <typename WritePortalType>
223 struct MultiplexerCreateWritePortalFunctor
224 {
225  template <typename StorageType>
226  VISKORES_CONT WritePortalType
227  operator()(StorageType,
228  const std::vector<viskores::cont::internal::Buffer>& buffers,
230  viskores::cont::Token& token) const
231  {
232  return WritePortalType(StorageType::CreateWritePortal(buffers, device, token));
233  }
234 };
235 
236 template <typename T, typename... Ss>
237 struct MultiplexerArrayHandleVariantFunctor
238 {
239  using VariantType = viskores::cont::Variant<viskores::cont::ArrayHandle<T, Ss>...>;
240 
241  template <typename StorageTag>
242  VISKORES_CONT VariantType operator()(viskores::cont::internal::Storage<T, StorageTag>,
243  const std::vector<viskores::cont::internal::Buffer>& buffers)
244  {
245  return VariantType(viskores::cont::ArrayHandle<T, StorageTag>(buffers));
246  }
247 };
248 
249 } // namespace detail
250 
251 template <typename ValueType, typename... StorageTags>
252 class Storage<ValueType, StorageTagMultiplexer<StorageTags...>>
253 {
254  template <typename S>
255  using StorageFor = viskores::cont::internal::Storage<ValueType, S>;
256 
257  using StorageVariant = viskores::cont::Variant<StorageFor<StorageTags>...>;
258 
259  VISKORES_CONT static StorageVariant Variant(
260  const std::vector<viskores::cont::internal::Buffer>& buffers)
261  {
262  return buffers[0].GetMetaData<StorageVariant>();
263  }
264 
265  VISKORES_CONT static std::vector<viskores::cont::internal::Buffer> ArrayBuffers(
266  const std::vector<viskores::cont::internal::Buffer>& buffers)
267  {
268  return std::vector<viskores::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
269  }
270 
271 public:
272  using ReadPortalType =
273  viskores::internal::ArrayPortalMultiplexer<typename StorageFor<StorageTags>::ReadPortalType...>;
274  using WritePortalType = viskores::internal::ArrayPortalMultiplexer<
275  typename StorageFor<StorageTags>::WritePortalType...>;
276 
277  VISKORES_CONT static viskores::IdComponent GetNumberOfComponentsFlat(
278  const std::vector<viskores::cont::internal::Buffer>& buffers)
279  {
280  return Variant(buffers).CastAndCall(detail::MultiplexerGetNumberOfComponentsFlatFunctor{},
281  ArrayBuffers(buffers));
282  }
283 
284  VISKORES_CONT static viskores::Id GetNumberOfValues(
285  const std::vector<viskores::cont::internal::Buffer>& buffers)
286  {
287  return Variant(buffers).CastAndCall(detail::MultiplexerGetNumberOfValuesFunctor{},
288  ArrayBuffers(buffers));
289  }
290 
291  VISKORES_CONT static void ResizeBuffers(
292  viskores::Id numValues,
293  const std::vector<viskores::cont::internal::Buffer>& buffers,
294  viskores::CopyFlag preserve,
295  viskores::cont::Token& token)
296  {
297  Variant(buffers).CastAndCall(
298  detail::MultiplexerResizeBuffersFunctor{}, numValues, ArrayBuffers(buffers), preserve, token);
299  }
300 
301  VISKORES_CONT static void Fill(const std::vector<viskores::cont::internal::Buffer>& buffers,
302  const ValueType& fillValue,
303  viskores::Id startIndex,
304  viskores::Id endIndex,
305  viskores::cont::Token& token)
306  {
307  Variant(buffers).CastAndCall(detail::MultiplexerFillFunctor{},
308  ArrayBuffers(buffers),
309  fillValue,
310  startIndex,
311  endIndex,
312  token);
313  }
314 
315  VISKORES_CONT static ReadPortalType CreateReadPortal(
316  const std::vector<viskores::cont::internal::Buffer>& buffers,
318  viskores::cont::Token& token)
319  {
320  return Variant(buffers).CastAndCall(
321  detail::MultiplexerCreateReadPortalFunctor<ReadPortalType>{},
322  ArrayBuffers(buffers),
323  device,
324  token);
325  }
326 
327  VISKORES_CONT static WritePortalType CreateWritePortal(
328  const std::vector<viskores::cont::internal::Buffer>& buffers,
330  viskores::cont::Token& token)
331  {
332  return Variant(buffers).CastAndCall(
333  detail::MultiplexerCreateWritePortalFunctor<WritePortalType>{},
334  ArrayBuffers(buffers),
335  device,
336  token);
337  }
338 
339  VISKORES_CONT static bool IsValid(const std::vector<viskores::cont::internal::Buffer>& buffers)
340  {
341  return Variant(buffers).IsValid();
342  }
343 
344  template <typename ArrayType>
345  VISKORES_CONT static std::vector<viskores::cont::internal::Buffer> CreateBuffers(
346  const ArrayType& array)
347  {
348  VISKORES_IS_ARRAY_HANDLE(ArrayType);
349  return viskores::cont::internal::CreateBuffers(StorageVariant{ array.GetStorage() }, array);
350  }
351 
352  VISKORES_CONT static std::vector<viskores::cont::internal::Buffer> CreateBuffers()
353  {
354  return viskores::cont::internal::CreateBuffers(StorageVariant{});
355  }
356 
357  VISKORES_CONT static
358  typename detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>::VariantType
359  GetArrayHandleVariant(const std::vector<viskores::cont::internal::Buffer>& buffers)
360  {
361  return Variant(buffers).CastAndCall(
362  detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>{},
363  ArrayBuffers(buffers));
364  }
365 };
366 
367 } // namespace internal
368 
369 namespace detail
370 {
371 
372 template <typename... ArrayHandleTypes>
373 struct ArrayHandleMultiplexerTraits
374 {
375  using ArrayHandleType0 = viskores::ListAt<viskores::List<ArrayHandleTypes...>, 0>;
376  VISKORES_IS_ARRAY_HANDLE(ArrayHandleType0);
377  using ValueType = typename ArrayHandleType0::ValueType;
378 
379  // If there is a compile error in this group of lines, then one of the array types given to
380  // ArrayHandleMultiplexer must contain an invalid ArrayHandle. That could mean that it is not an
381  // ArrayHandle type or it could mean that the value type does not match the appropriate value
382  // type.
383  template <typename ArrayHandle>
384  struct CheckArrayHandleTransform
385  {
386  VISKORES_IS_ARRAY_HANDLE(ArrayHandle);
387  VISKORES_STATIC_ASSERT((std::is_same<ValueType, typename ArrayHandle::ValueType>::value));
388  };
390 
391  // Note that this group of code could be simplified as the pair of lines:
392  // template <typename ArrayHandle>
393  // using ArrayHandleToStorageTag = typename ArrayHandle::StorageTag;
394  // However, there are issues with older Visual Studio compilers that is not working
395  // correctly with that form.
396  template <typename ArrayHandle>
397  struct ArrayHandleToStorageTagImpl
398  {
399  using Type = typename ArrayHandle::StorageTag;
400  };
401  template <typename ArrayHandle>
402  using ArrayHandleToStorageTag = typename ArrayHandleToStorageTagImpl<ArrayHandle>::Type;
403 
404  using StorageTag =
406  using StorageType = viskores::cont::internal::Storage<ValueType, StorageTag>;
407 };
408 } // namespace detail
409 
429 template <typename... ArrayHandleTypes>
432  typename detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>::ValueType,
433  typename detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>::StorageTag>
434 {
435  using Traits = detail::ArrayHandleMultiplexerTraits<ArrayHandleTypes...>;
436 
437 public:
442 
443  template <typename RealStorageTag>
446  : Superclass(StorageType::CreateBuffers(src))
447  {
448  }
449 
450  VISKORES_CONT bool IsValid() const { return StorageType::IsValid(this->GetBuffers()); }
451 
452  template <typename S>
454  {
455  this->SetBuffers(StorageType::CreateBuffers(src));
456  }
457 
459  -> decltype(StorageType::GetArrayHandleVariant(this->GetBuffers()))
460  {
461  return StorageType::GetArrayHandleVariant(this->GetBuffers());
462  }
463 };
464 
471 template <typename List>
473 
474 namespace internal
475 {
476 
477 namespace detail
478 {
479 
480 struct ArrayExtractComponentMultiplexerFunctor
481 {
482  template <typename ArrayType>
483  auto operator()(const ArrayType& array,
484  viskores::IdComponent componentIndex,
485  viskores::CopyFlag allowCopy) const
486  -> decltype(viskores::cont::ArrayExtractComponent(array, componentIndex, allowCopy))
487  {
488  return viskores::cont::internal::ArrayExtractComponentImpl<typename ArrayType::StorageTag>{}(
489  array, componentIndex, allowCopy);
490  }
491 };
492 
493 } // namespace detail
494 
495 template <typename... Ss>
496 struct ArrayExtractComponentImpl<viskores::cont::StorageTagMultiplexer<Ss...>>
497 {
498  template <typename T>
501  viskores::IdComponent componentIndex,
502  viskores::CopyFlag allowCopy)
503  {
505  return array.GetArrayHandleVariant().CastAndCall(
506  detail::ArrayExtractComponentMultiplexerFunctor{}, componentIndex, allowCopy);
507  }
508 };
509 
510 } // namespace internal
511 
512 } // namespace cont
513 
514 } // namespace viskores
515 
516 #endif //viskores_cont_ArrayHandleMultiplexer_h
viskores::cont::ArrayHandleMultiplexer::SetArray
void SetArray(const viskores::cont::ArrayHandle< ValueType, S > &src)
Definition: ArrayHandleMultiplexer.h:453
ArrayHandle.h
ArrayExtractComponent.h
viskores::cont::ArrayHandle::StorageTag
StorageTag_ StorageTag
Definition: ArrayHandle.h:321
viskores::cont::ArrayHandleMultiplexer::Traits
detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... > Traits
Definition: ArrayHandleMultiplexer.h:435
viskores::cont::ArrayHandle< detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::ValueType, detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::StorageTag >::SetBuffers
void SetBuffers(const std::vector< viskores::cont::internal::Buffer > &buffers)
Definition: ArrayHandle.h:757
ArrayHandleCast.h
viskores::cont::ArrayHandleMultiplexer
An ArrayHandle that can behave like several other handles.
Definition: ArrayHandleMultiplexer.h:430
VISKORES_IS_ARRAY_HANDLE
#define VISKORES_IS_ARRAY_HANDLE(T)
Checks that the given type is a viskores::cont::ArrayHandle.
Definition: ArrayHandle.h:145
Variant.h
viskores::cont::ArrayHandleMultiplexer::StorageType
typename Superclass::StorageType StorageType
Definition: ArrayHandleMultiplexer.h:441
viskores::ListApply
typename detail::ListApplyImpl< List, Target >::type ListApply
Applies the list of types to a template.
Definition: List.h:146
Variant.h
VISKORES_SUPPRESS_EXEC_WARNINGS
#define VISKORES_SUPPRESS_EXEC_WARNINGS
Definition: ExportMacros.h:61
viskores::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:313
Assert.h
viskores::IdComponent
viskores::Int32 IdComponent
Base type to use to index small lists.
Definition: Types.h:202
VISKORES_EXEC_CONT
#define VISKORES_EXEC_CONT
Definition: ExportMacros.h:60
viskores::cont::ArrayHandleStride
An ArrayHandle that accesses a basic array with strides and offsets.
Definition: ArrayHandleStride.h:343
viskores::cont::ArrayHandleMultiplexer::IsValid
bool IsValid() const
Definition: ArrayHandleMultiplexer.h:450
viskores::List
A template used to hold a list of types.
Definition: List.h:47
TypeTraits.h
ArrayHandleUniformPointCoordinates.h
viskores::cont::ArrayExtractComponent
viskores::cont::ArrayHandleStride< typename viskores::VecTraits< T >::BaseComponentType > ArrayExtractComponent(const viskores::cont::ArrayHandle< T, S > &src, viskores::IdComponent componentIndex, viskores::CopyFlag allowCopy=viskores::CopyFlag::On)
Pulls a component out of an ArrayHandle.
Definition: ArrayExtractComponent.h:267
viskores::ListAt
typename detail::ListAtImpl< List, Index >::type ListAt
Finds the type at the given index.
Definition: List.h:358
viskores::Id
viskores::Int64 Id
Base type to use to index arrays.
Definition: Types.h:235
VISKORES_CONT
#define VISKORES_CONT
Definition: ExportMacros.h:65
viskores
Groups connected points that have the same field value.
Definition: Atomic.h:27
ArrayHandleCartesianProduct.h
VISKORES_ASSERT
#define VISKORES_ASSERT(condition)
Definition: Assert.h:51
viskores::cont::ArrayHandleMultiplexer::ArrayHandleMultiplexer
ArrayHandleMultiplexer(const viskores::cont::ArrayHandle< ValueType, RealStorageTag > &src)
Definition: ArrayHandleMultiplexer.h:444
viskores::cont::DeviceAdapterId
An object used to specify a device.
Definition: DeviceAdapterTag.h:66
VISKORES_ARRAY_HANDLE_SUBCLASS
#define VISKORES_ARRAY_HANDLE_SUBCLASS(classname, fullclasstype, superclass)
Macro to make default methods in ArrayHandle subclasses.
Definition: ArrayHandle.h:256
viskores::cont::ArrayHandleMultiplexerFromList
viskores::ListApply< List, ArrayHandleMultiplexer > ArrayHandleMultiplexerFromList
Converts aviskores::List to an ArrayHandleMultiplexer
Definition: ArrayHandleMultiplexer.h:472
viskores::Get
auto Get(const viskores::Tuple< Ts... > &tuple)
Retrieve the object from a viskores::Tuple at the given index.
Definition: Tuple.h:89
viskores::cont::StorageTagMultiplexer
Definition: ArrayHandleMultiplexer.h:149
viskores::cont::ArrayHandleMultiplexer::Superclass
typename viskores::cont::detail::GetTypeInParentheses< void(viskores::cont::ArrayHandle< typename Traits::ValueType, typename Traits::StorageTag >) >::type Superclass
Definition: ArrayHandleMultiplexer.h:441
viskores::CopyFlag
CopyFlag
Identifier used to specify whether a function should deep copy data.
Definition: Flags.h:25
viskores::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:43
viskores::cont::ArrayHandleMultiplexer::GetArrayHandleVariant
auto GetArrayHandleVariant() const -> decltype(StorageType::GetArrayHandleVariant(this->GetBuffers()))
Definition: ArrayHandleMultiplexer.h:458
viskores::cont::ArrayHandle< detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::ValueType, detail::ArrayHandleMultiplexerTraits< ArrayHandleTypes... >::StorageTag >::GetBuffers
const std::vector< viskores::cont::internal::Buffer > & GetBuffers() const
Returns the internal Buffer structures that hold the data.
Definition: ArrayHandle.h:738
VISKORES_STATIC_ASSERT
#define VISKORES_STATIC_ASSERT(condition)
Definition: StaticAssert.h:24