10 #ifndef vtk_m_ArrayHandleDecorator_h
11 #define vtk_m_ArrayHandleDecorator_h
24 #include <vtkmstd/integer_sequence.h>
28 #include <type_traits>
40 struct NoOpInverseFunctor
42 NoOpInverseFunctor() =
default;
43 template <
typename... Ts>
47 template <
typename VT>
58 template <
typename ValueType_,
typename FunctorType_,
typename InverseFunctorType_>
62 using ValueType = ValueType_;
63 using FunctorType = FunctorType_;
64 using InverseFunctorType = InverseFunctorType_;
65 using ReadOnly = std::is_same<InverseFunctorType, decor::NoOpInverseFunctor>;
68 ArrayPortalDecorator() {}
71 ArrayPortalDecorator(FunctorType func, InverseFunctorType iFunc,
vtkm::Id numValues)
73 , InverseFunctor(iFunc)
74 , NumberOfValues(numValues)
79 vtkm::Id GetNumberOfValues()
const {
return this->NumberOfValues; }
82 ValueType
Get(
vtkm::Id index)
const {
return this->Functor(index); }
84 template <
typename ReadOnly_ = ReadOnly,
85 typename =
typename std::enable_if<!ReadOnly_::value>::type>
88 this->InverseFunctor(index, value);
93 InverseFunctorType InverseFunctor;
112 template <
typename ArrayHandleList>
119 template <
typename DecoratorImplT,
typename PortalList>
120 struct IsFunctorInvertibleImpl;
122 template <
typename DecoratorImplT,
template <
typename...>
class List,
typename... PortalTs>
123 struct IsFunctorInvertibleImpl<DecoratorImplT, List<PortalTs...>>
128 typename U = decltype(std::declval<T>().CreateInverseFunctor(std::declval<PortalTs&&>()...))>
129 static std::true_type InverseExistsTest(
int);
131 template <
typename T>
132 static std::false_type InverseExistsTest(...);
135 using type = decltype(InverseExistsTest<DecoratorImplT>(0));
139 template <
typename DecoratorImplT,
typename ArrayList>
140 struct IsDecoratorAllocatableImpl;
142 template <
typename DecoratorImplT,
template <
typename...>
class List,
typename... ArrayTs>
143 struct IsDecoratorAllocatableImpl<DecoratorImplT, List<ArrayTs...>>
148 typename U = decltype(std::declval<T>().AllocateSourceArrays(0,
150 std::declval<vtkm::cont::Token&>(),
151 std::declval<ArrayTs&>()...))>
152 static std::true_type Exists(
int);
153 template <
typename T>
154 static std::false_type Exists(...);
157 using type = decltype(Exists<DecoratorImplT>(0));
162 template <
typename DecoratorImplT,
typename PortalList>
163 struct GetFunctorTypeImpl;
165 template <
typename DecoratorImplT,
template <
typename...>
class List,
typename... PortalTs>
166 struct GetFunctorTypeImpl<DecoratorImplT, List<PortalTs...>>
169 decltype(std::declval<DecoratorImplT>().CreateFunctor(std::declval<PortalTs&&>()...));
175 template <
typename CanWrite,
typename DecoratorImplT,
typename PortalList>
176 struct GetInverseFunctorTypeImpl;
178 template <
typename DecoratorImplT,
template <
typename...>
class List,
typename... PortalTs>
179 struct GetInverseFunctorTypeImpl<std::true_type, DecoratorImplT, List<PortalTs...>>
182 decltype(std::declval<DecoratorImplT>().CreateInverseFunctor(std::declval<PortalTs&&>()...));
185 template <
typename DecoratorImplT,
typename PortalList>
186 struct GetInverseFunctorTypeImpl<std::false_type, DecoratorImplT, PortalList>
188 using type = vtkm::internal::decor::NoOpInverseFunctor;
194 template <
typename ArrayT>
195 typename std::decay<ArrayT>::type::WritePortalType GetWritePortalImpl(
201 return ArrayT::StorageType::CreateWritePortal(array.GetBuffers(), device, token);
204 template <
typename ArrayT>
205 typename std::decay<ArrayT>::type::ReadPortalType GetWritePortalImpl(
211 return ArrayT::StorageType::CreateReadPortal(array.GetBuffers(), device, token);
222 template <
typename ArrayT>
223 using GetWritePortalType = std::conditional_t<
224 vtkm::internal::PortalSupportsSets<typename std::decay<ArrayT>::type::WritePortalType>::value,
225 typename std::decay<ArrayT>::type::WritePortalType,
226 typename std::decay<ArrayT>::type::ReadPortalType>;
228 template <
typename ArrayT>
229 using GetReadPortalType =
typename std::decay<ArrayT>::type::ReadPortalType;
233 template <
typename ArrayT>
234 GetWritePortalType<typename std::decay<ArrayT>::type>
237 return detail::GetWritePortalImpl(
238 IsWritableArrayHandle<ArrayT>{}, std::forward<ArrayT>(array), device, token);
241 template <
typename ArrayT>
242 GetReadPortalType<typename std::decay<ArrayT>::type> ReadPortal(
const ArrayT& array,
246 return ArrayT::StorageType::CreateReadPortal(array.GetBuffers(), device, token);
251 template <
typename PortalList>
256 template <
typename DecoratorImplT,
typename PortalList>
257 using IsFunctorInvertible =
258 typename detail::IsFunctorInvertibleImpl<DecoratorImplT, PortalList>::type;
262 template <
typename DecoratorImplT,
typename ArrayList>
263 using IsDecoratorAllocatable =
264 typename detail::IsDecoratorAllocatableImpl<DecoratorImplT, ArrayList>::type;
268 template <
typename DecoratorImplT,
typename PortalList>
269 using CanWriteToFunctor = vtkm::internal::meta::And<IsFunctorInvertible<DecoratorImplT, PortalList>,
270 AnyPortalIsWritable<PortalList>>;
273 template <
typename DecoratorImplT,
typename PortalList>
274 using GetFunctorType =
typename detail::GetFunctorTypeImpl<DecoratorImplT, PortalList>::type;
278 template <
typename DecoratorImplT,
typename PortalList>
279 using GetInverseFunctorType =
280 typename detail::GetInverseFunctorTypeImpl<CanWriteToFunctor<DecoratorImplT, PortalList>,
298 template <
typename... ArrayTs>
299 using GetReadPortalList =
301 std::declval<vtkm::cont::DeviceAdapterId>(),
302 std::declval<vtkm::cont::Token&>())))...>;
304 template <
typename... ArrayTs>
305 using GetWritePortalList =
307 std::declval<vtkm::cont::DeviceAdapterId>(),
308 std::declval<vtkm::cont::Token&>())))...>;
310 template <
typename DecoratorImplT, std::
size_t NumArrays>
311 struct DecoratorMetaData
313 DecoratorImplT Implementation;
315 std::array<std::size_t, NumArrays + 1> BufferOffsets;
317 template <
typename... ArrayTs>
318 DecoratorMetaData(
const DecoratorImplT& implementation,
320 const ArrayTs... arrays)
321 : Implementation(implementation)
322 , NumberOfValues(numValues)
324 auto numBuffers = { std::size_t{ 1 }, arrays.GetBuffers().size()... };
325 std::partial_sum(numBuffers.begin(), numBuffers.end(), this->BufferOffsets.begin());
328 DecoratorMetaData() =
default;
331 template <
typename DecoratorImplT,
typename... ArrayTs>
332 struct DecoratorStorageTraits
337 "Must specify at least one source array handle for "
338 "ArrayHandleDecorator. Consider using "
339 "ArrayHandleImplicit instead.");
345 "Trailing template parameters for "
346 "ArrayHandleDecorator must be a list of ArrayHandle "
352 using IndexList = vtkmstd::make_index_sequence<
sizeof...(ArrayTs)>;
354 using MetaData = DecoratorMetaData<DecoratorImplT,
sizeof...(ArrayTs)>;
356 static MetaData& GetMetaData(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
358 return buffers[0].GetMetaData<MetaData>();
362 template <vtkm::IdComponent I>
364 const std::vector<vtkm::cont::internal::Buffer>& buffers)
366 const MetaData& metaData = GetMetaData(buffers);
367 std::vector<vtkm::cont::internal::Buffer> subBuffers(
368 buffers.begin() + metaData.BufferOffsets[I], buffers.begin() + metaData.BufferOffsets[I + 1]);
373 using IsAllocatable = IsDecoratorAllocatable<DecoratorImplT, ArrayList>;
378 using WritePortalList = GetWritePortalList<ArrayTs...>;
379 using ReadPortalList = GetReadPortalList<ArrayTs...>;
382 using WriteFunctorType = GetFunctorType<DecoratorImplT, WritePortalList>;
383 using ReadFunctorType = GetFunctorType<DecoratorImplT, ReadPortalList>;
386 using InverseWriteFunctorType = GetInverseFunctorType<DecoratorImplT, WritePortalList>;
388 using InverseReadFunctorType = vtkm::internal::decor::NoOpInverseFunctor;
392 using ValueType = decltype(std::declval<WriteFunctorType>()(0));
395 using WritePortalType =
396 vtkm::internal::ArrayPortalDecorator<ValueType, WriteFunctorType, InverseWriteFunctorType>;
398 using ReadPortalType =
399 vtkm::internal::ArrayPortalDecorator<ValueType, ReadFunctorType, InverseReadFunctorType>;
406 template <
typename DecoratorPortalType,
typename... PortalTs>
408 typename std::enable_if<DecoratorPortalType::ReadOnly::value, DecoratorPortalType>::type
409 CreatePortalDecorator(
vtkm::Id numVals,
const DecoratorImplT& impl, PortalTs&&... portals)
411 return { impl.CreateFunctor(std::forward<PortalTs>(portals)...),
412 typename DecoratorPortalType::InverseFunctorType{},
416 template <
typename DecoratorPortalType,
typename... PortalTs>
418 typename std::enable_if<!DecoratorPortalType::ReadOnly::value, DecoratorPortalType>::type
419 CreatePortalDecorator(
vtkm::Id numVals,
const DecoratorImplT& impl, PortalTs... portals)
421 return { impl.CreateFunctor(portals...), impl.CreateInverseFunctor(portals...), numVals };
425 VTKM_CONT [[noreturn]]
static void CallAllocate(std::false_type,
427 const std::vector<vtkm::cont::internal::Buffer>&,
435 VTKM_CONT static void CallAllocate(std::true_type,
437 const std::vector<vtkm::cont::internal::Buffer>& buffers,
442 MetaData& metadata = GetMetaData(buffers);
443 metadata.Implementation.AllocateSourceArrays(newSize, preserve, token, arrays...);
444 metadata.NumberOfValues = newSize;
449 template <std::size_t... Indices>
450 VTKM_CONT static WritePortalType CreateWritePortal(
451 const std::vector<vtkm::cont::internal::Buffer>& buffers,
453 vtkmstd::index_sequence<Indices...>,
457 return CreatePortalDecorator<WritePortalType>(
459 GetMetaData(buffers).Implementation,
460 WritePortal(BuffersToArray<Indices>(buffers), device, token)...);
463 template <std::size_t... Indices>
464 VTKM_CONT static ReadPortalType CreateReadPortal(
465 const std::vector<vtkm::cont::internal::Buffer>& buffers,
467 vtkmstd::index_sequence<Indices...>,
471 return CreatePortalDecorator<ReadPortalType>(
473 GetMetaData(buffers).Implementation,
474 ReadPortal(BuffersToArray<Indices>(buffers), device, token)...);
477 template <std::size_t... Indices>
478 VTKM_CONT static void AllocateSourceArrays(
480 const std::vector<vtkm::cont::internal::Buffer>& buffers,
483 vtkmstd::index_sequence<Indices...>)
486 IsAllocatable{}, numValues, buffers, preserve, token, BuffersToArray<Indices>(buffers)...);
492 template <
typename DecoratorImplT,
typename... ArrayTs>
497 template <
typename DecoratorImplT,
typename... ArrayTs>
498 class Storage<typename decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>::ValueType,
499 StorageTagDecorator<DecoratorImplT, ArrayTs...>>
501 using Traits = decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>;
502 using IndexList =
typename Traits::IndexList;
503 using MetaData =
typename Traits::MetaData;
506 using ReadPortalType =
typename Traits::ReadPortalType;
507 using WritePortalType =
typename Traits::WritePortalType;
510 const std::vector<vtkm::cont::internal::Buffer>& buffers)
512 return Traits::GetMetaData(buffers).NumberOfValues;
516 const std::vector<vtkm::cont::internal::Buffer>& buffers,
520 if (numValues != GetNumberOfValues(buffers))
522 Traits::AllocateSourceArrays(numValues, buffers, preserve, token, IndexList{});
531 VTKM_CONT static ReadPortalType CreateReadPortal(
532 const std::vector<vtkm::cont::internal::Buffer>& buffers,
536 return Traits::CreateReadPortal(
537 buffers, GetNumberOfValues(buffers), IndexList{}, device, token);
540 VTKM_CONT static WritePortalType CreateWritePortal(
541 const std::vector<vtkm::cont::internal::Buffer>& buffers,
545 return Traits::CreateWritePortal(
546 buffers, GetNumberOfValues(buffers), IndexList{}, device, token);
549 VTKM_CONT static std::vector<vtkm::cont::internal::Buffer>
550 CreateBuffers(
const DecoratorImplT& implementation,
vtkm::Id numValues,
const ArrayTs&... arrays)
552 return vtkm::cont::internal::CreateBuffers(MetaData(implementation, numValues, arrays...),
556 VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
558 return CreateBuffers(DecoratorImplT{}, 0, ArrayTs{}...);
562 template <
typename DecoratorImplT,
typename... ArrayTs>
563 struct DecoratorHandleTraits
565 using StorageTraits = decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>;
566 using ValueType =
typename StorageTraits::ValueType;
567 using StorageTag = StorageTagDecorator<DecoratorImplT, ArrayTs...>;
568 using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
646 template <
typename DecoratorImplT,
typename... ArrayTs>
648 :
public internal::DecoratorHandleTraits<typename std::decay<DecoratorImplT>::type,
649 typename std::decay<ArrayTs>::type...>::Superclass
652 using Traits = internal::DecoratorHandleTraits<typename std::decay<DecoratorImplT>::type,
653 typename std::decay<ArrayTs>::type...>;
659 typename std::decay<ArrayTs>::type...>),
664 const typename std::decay<DecoratorImplT>::type& impl,
665 const typename std::decay<ArrayTs>::type&... arrays)
666 : Superclass{ StorageType::CreateBuffers(impl, numValues, arrays...) }
674 template <
typename DecoratorImplT,
typename... ArrayTs>
675 VTKM_CONT ArrayHandleDecorator<typename std::decay<DecoratorImplT>::type,
676 typename std::decay<ArrayTs>::type...>
681 "Must specify at least one source array handle for "
682 "ArrayHandleDecorator. Consider using "
683 "ArrayHandleImplicit instead.");
685 "Trailing template parameters for "
686 "ArrayHandleDecorator must be a list of ArrayHandle "
689 return { numValues, std::forward<DecoratorImplT>(f), std::forward<ArrayTs>(arrays)... };
694 #ifdef VTKM_USE_TAO_SEQ
695 #undef VTKM_USE_TAO_SEQ
698 #endif //vtk_m_ArrayHandleDecorator_h