18 #ifndef viskores_ArrayHandleDecorator_h
19 #define viskores_ArrayHandleDecorator_h
32 #include <viskoresstd/integer_sequence.h>
36 #include <type_traits>
48 struct NoOpInverseFunctor
50 NoOpInverseFunctor() =
default;
51 template <
typename... Ts>
55 template <
typename VT>
66 template <
typename ValueType_,
typename FunctorType_,
typename InverseFunctorType_>
67 class VISKORES_ALWAYS_EXPORT ArrayPortalDecorator
70 using ValueType = ValueType_;
71 using FunctorType = FunctorType_;
72 using InverseFunctorType = InverseFunctorType_;
73 using ReadOnly = std::is_same<InverseFunctorType, decor::NoOpInverseFunctor>;
76 ArrayPortalDecorator() {}
79 ArrayPortalDecorator(FunctorType func, InverseFunctorType iFunc,
viskores::Id numValues)
81 , InverseFunctor(iFunc)
82 , NumberOfValues(numValues)
87 viskores::Id GetNumberOfValues()
const {
return this->NumberOfValues; }
90 ValueType
Get(
viskores::Id index)
const {
return this->Functor(index); }
92 template <
typename ReadOnly_ = ReadOnly,
93 typename =
typename std::enable_if<!ReadOnly_::value>::type>
96 this->InverseFunctor(index, value);
101 InverseFunctorType InverseFunctor;
120 template <
typename ArrayHandleList>
121 using AllAreArrayHandles =
128 template <
typename DecoratorImplT,
typename PortalList>
129 struct IsFunctorInvertibleImpl;
131 template <
typename DecoratorImplT,
template <
typename...>
class List,
typename... PortalTs>
132 struct IsFunctorInvertibleImpl<DecoratorImplT, List<PortalTs...>>
137 typename U = decltype(std::declval<T>().CreateInverseFunctor(std::declval<PortalTs&&>()...))>
138 static std::true_type InverseExistsTest(
int);
140 template <
typename T>
141 static std::false_type InverseExistsTest(...);
144 using type = decltype(InverseExistsTest<DecoratorImplT>(0));
148 template <
typename DecoratorImplT,
typename ArrayList>
149 struct IsDecoratorAllocatableImpl;
151 template <
typename DecoratorImplT,
template <
typename...>
class List,
typename... ArrayTs>
152 struct IsDecoratorAllocatableImpl<DecoratorImplT, List<ArrayTs...>>
155 template <
typename T,
156 typename U = decltype(std::declval<T>().AllocateSourceArrays(
159 std::declval<viskores::cont::Token&>(),
160 std::declval<ArrayTs&>()...))>
161 static std::true_type Exists(
int);
162 template <
typename T>
163 static std::false_type Exists(...);
166 using type = decltype(Exists<DecoratorImplT>(0));
171 template <
typename DecoratorImplT,
typename PortalList>
172 struct GetFunctorTypeImpl;
174 template <
typename DecoratorImplT,
template <
typename...>
class List,
typename... PortalTs>
175 struct GetFunctorTypeImpl<DecoratorImplT, List<PortalTs...>>
178 decltype(std::declval<DecoratorImplT>().CreateFunctor(std::declval<PortalTs&&>()...));
184 template <
typename CanWrite,
typename DecoratorImplT,
typename PortalList>
185 struct GetInverseFunctorTypeImpl;
187 template <
typename DecoratorImplT,
template <
typename...>
class List,
typename... PortalTs>
188 struct GetInverseFunctorTypeImpl<std::true_type, DecoratorImplT, List<PortalTs...>>
191 decltype(std::declval<DecoratorImplT>().CreateInverseFunctor(std::declval<PortalTs&&>()...));
194 template <
typename DecoratorImplT,
typename PortalList>
195 struct GetInverseFunctorTypeImpl<std::false_type, DecoratorImplT, PortalList>
197 using type = viskores::internal::decor::NoOpInverseFunctor;
203 template <
typename ArrayT>
204 typename std::decay<ArrayT>::type::WritePortalType GetWritePortalImpl(
210 return ArrayT::StorageType::CreateWritePortal(array.GetBuffers(), device, token);
213 template <
typename ArrayT>
214 typename std::decay<ArrayT>::type::ReadPortalType GetWritePortalImpl(
220 return ArrayT::StorageType::CreateReadPortal(array.GetBuffers(), device, token);
231 template <
typename ArrayT>
232 using GetWritePortalType = std::conditional_t<
233 viskores::internal::PortalSupportsSets<typename std::decay<ArrayT>::type::WritePortalType>::value,
234 typename std::decay<ArrayT>::type::WritePortalType,
235 typename std::decay<ArrayT>::type::ReadPortalType>;
237 template <
typename ArrayT>
238 using GetReadPortalType =
typename std::decay<ArrayT>::type::ReadPortalType;
242 template <
typename ArrayT>
243 GetWritePortalType<typename std::decay<ArrayT>::type>
246 return detail::GetWritePortalImpl(
247 IsWritableArrayHandle<ArrayT>{}, std::forward<ArrayT>(array), device, token);
250 template <
typename ArrayT>
251 GetReadPortalType<typename std::decay<ArrayT>::type> ReadPortal(
256 return ArrayT::StorageType::CreateReadPortal(array.GetBuffers(), device, token);
261 template <
typename PortalList>
266 template <
typename DecoratorImplT,
typename PortalList>
267 using IsFunctorInvertible =
268 typename detail::IsFunctorInvertibleImpl<DecoratorImplT, PortalList>::type;
272 template <
typename DecoratorImplT,
typename ArrayList>
273 using IsDecoratorAllocatable =
274 typename detail::IsDecoratorAllocatableImpl<DecoratorImplT, ArrayList>::type;
278 template <
typename DecoratorImplT,
typename PortalList>
279 using CanWriteToFunctor =
280 viskores::internal::meta::And<IsFunctorInvertible<DecoratorImplT, PortalList>,
281 AnyPortalIsWritable<PortalList>>;
284 template <
typename DecoratorImplT,
typename PortalList>
285 using GetFunctorType =
typename detail::GetFunctorTypeImpl<DecoratorImplT, PortalList>::type;
289 template <
typename DecoratorImplT,
typename PortalList>
290 using GetInverseFunctorType =
291 typename detail::GetInverseFunctorTypeImpl<CanWriteToFunctor<DecoratorImplT, PortalList>,
309 template <
typename... ArrayTs>
310 using GetReadPortalList =
312 std::declval<viskores::cont::DeviceAdapterId>(),
313 std::declval<viskores::cont::Token&>())))...>;
315 template <
typename... ArrayTs>
316 using GetWritePortalList =
318 std::declval<viskores::cont::DeviceAdapterId>(),
319 std::declval<viskores::cont::Token&>())))...>;
321 template <
typename DecoratorImplT, std::
size_t NumArrays>
322 struct DecoratorMetaData
324 DecoratorImplT Implementation;
326 std::array<std::size_t, NumArrays + 1> BufferOffsets;
328 template <
typename... ArrayTs>
329 DecoratorMetaData(
const DecoratorImplT& implementation,
331 const ArrayTs... arrays)
332 : Implementation(implementation)
333 , NumberOfValues(numValues)
335 auto numBuffers = { std::size_t{ 1 }, arrays.GetBuffers().size()... };
336 std::partial_sum(numBuffers.begin(), numBuffers.end(), this->BufferOffsets.begin());
339 DecoratorMetaData() =
default;
342 template <
typename DecoratorImplT,
typename... ArrayTs>
343 struct DecoratorStorageTraits
348 "Must specify at least one source array handle for "
349 "ArrayHandleDecorator. Consider using "
350 "ArrayHandleImplicit instead.");
356 "Trailing template parameters for "
357 "ArrayHandleDecorator must be a list of ArrayHandle "
363 using IndexList = viskoresstd::make_index_sequence<
sizeof...(ArrayTs)>;
365 using MetaData = DecoratorMetaData<DecoratorImplT,
sizeof...(ArrayTs)>;
367 static MetaData& GetMetaData(
const std::vector<viskores::cont::internal::Buffer>& buffers)
369 return buffers[0].GetMetaData<MetaData>();
373 template <viskores::IdComponent I>
375 const std::vector<viskores::cont::internal::Buffer>& buffers)
377 const MetaData& metaData = GetMetaData(buffers);
378 std::vector<viskores::cont::internal::Buffer> subBuffers(
379 buffers.begin() + metaData.BufferOffsets[I], buffers.begin() + metaData.BufferOffsets[I + 1]);
384 using IsAllocatable = IsDecoratorAllocatable<DecoratorImplT, ArrayList>;
389 using WritePortalList = GetWritePortalList<ArrayTs...>;
390 using ReadPortalList = GetReadPortalList<ArrayTs...>;
393 using WriteFunctorType = GetFunctorType<DecoratorImplT, WritePortalList>;
394 using ReadFunctorType = GetFunctorType<DecoratorImplT, ReadPortalList>;
397 using InverseWriteFunctorType = GetInverseFunctorType<DecoratorImplT, WritePortalList>;
399 using InverseReadFunctorType = viskores::internal::decor::NoOpInverseFunctor;
403 using ValueType = decltype(std::declval<WriteFunctorType>()(0));
406 using WritePortalType =
407 viskores::internal::ArrayPortalDecorator<ValueType, WriteFunctorType, InverseWriteFunctorType>;
409 using ReadPortalType =
410 viskores::internal::ArrayPortalDecorator<ValueType, ReadFunctorType, InverseReadFunctorType>;
417 template <
typename DecoratorPortalType,
typename... PortalTs>
419 typename std::enable_if<DecoratorPortalType::ReadOnly::value, DecoratorPortalType>::type
420 CreatePortalDecorator(
viskores::Id numVals,
const DecoratorImplT& impl, PortalTs&&... portals)
422 return { impl.CreateFunctor(std::forward<PortalTs>(portals)...),
423 typename DecoratorPortalType::InverseFunctorType{},
427 template <
typename DecoratorPortalType,
typename... PortalTs>
429 typename std::enable_if<!DecoratorPortalType::ReadOnly::value, DecoratorPortalType>::type
430 CreatePortalDecorator(
viskores::Id numVals,
const DecoratorImplT& impl, PortalTs... portals)
432 return { impl.CreateFunctor(portals...), impl.CreateInverseFunctor(portals...), numVals };
439 const std::vector<viskores::cont::internal::Buffer>&,
450 const std::vector<viskores::cont::internal::Buffer>& buffers,
455 MetaData& metadata = GetMetaData(buffers);
456 metadata.Implementation.AllocateSourceArrays(newSize, preserve, token, arrays...);
457 metadata.NumberOfValues = newSize;
462 template <std::size_t... Indices>
464 const std::vector<viskores::cont::internal::Buffer>& buffers,
466 viskoresstd::index_sequence<Indices...>,
470 return CreatePortalDecorator<WritePortalType>(
472 GetMetaData(buffers).Implementation,
473 WritePortal(BuffersToArray<Indices>(buffers), device, token)...);
476 template <std::size_t... Indices>
478 const std::vector<viskores::cont::internal::Buffer>& buffers,
480 viskoresstd::index_sequence<Indices...>,
484 return CreatePortalDecorator<ReadPortalType>(
486 GetMetaData(buffers).Implementation,
487 ReadPortal(BuffersToArray<Indices>(buffers), device, token)...);
490 template <std::size_t... Indices>
493 const std::vector<viskores::cont::internal::Buffer>& buffers,
496 viskoresstd::index_sequence<Indices...>)
499 IsAllocatable{}, numValues, buffers, preserve, token, BuffersToArray<Indices>(buffers)...);
505 template <
typename DecoratorImplT,
typename... ArrayTs>
506 struct VISKORES_ALWAYS_EXPORT StorageTagDecorator
510 template <
typename DecoratorImplT,
typename... ArrayTs>
511 class Storage<typename decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>::ValueType,
512 StorageTagDecorator<DecoratorImplT, ArrayTs...>>
514 using Traits = decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>;
515 using IndexList =
typename Traits::IndexList;
516 using MetaData =
typename Traits::MetaData;
519 using ReadPortalType =
typename Traits::ReadPortalType;
520 using WritePortalType =
typename Traits::WritePortalType;
538 const std::vector<viskores::cont::internal::Buffer>&)
540 return GetNumberOfComponentsFlatImpl(
545 const std::vector<viskores::cont::internal::Buffer>& buffers)
547 return Traits::GetMetaData(buffers).NumberOfValues;
552 const std::vector<viskores::cont::internal::Buffer>& buffers,
556 if (numValues != GetNumberOfValues(buffers))
558 Traits::AllocateSourceArrays(numValues, buffers, preserve, token, IndexList{});
568 const std::vector<viskores::cont::internal::Buffer>& buffers,
572 return Traits::CreateReadPortal(
573 buffers, GetNumberOfValues(buffers), IndexList{}, device, token);
577 const std::vector<viskores::cont::internal::Buffer>& buffers,
581 return Traits::CreateWritePortal(
582 buffers, GetNumberOfValues(buffers), IndexList{}, device, token);
585 VISKORES_CONT static std::vector<viskores::cont::internal::Buffer> CreateBuffers(
586 const DecoratorImplT& implementation,
588 const ArrayTs&... arrays)
590 return viskores::cont::internal::CreateBuffers(MetaData(implementation, numValues, arrays...),
594 VISKORES_CONT static std::vector<viskores::cont::internal::Buffer> CreateBuffers()
596 return CreateBuffers(DecoratorImplT{}, 0, ArrayTs{}...);
600 template <
typename DecoratorImplT,
typename... ArrayTs>
601 struct DecoratorHandleTraits
603 using StorageTraits = decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>;
604 using ValueType =
typename StorageTraits::ValueType;
605 using StorageTag = StorageTagDecorator<DecoratorImplT, ArrayTs...>;
683 template <
typename DecoratorImplT,
typename... ArrayTs>
685 :
public internal::DecoratorHandleTraits<typename std::decay<DecoratorImplT>::type,
689 using Traits = internal::DecoratorHandleTraits<typename std::decay<DecoratorImplT>::type,
690 typename std::decay<ArrayTs>::type...>;
695 typename std::decay<ArrayTs>::type...>),
700 const typename std::decay<DecoratorImplT>::type& impl,
701 const typename std::decay<ArrayTs>::type&... arrays)
702 :
Superclass{ StorageType::CreateBuffers(impl, numValues, arrays...) }
710 template <
typename DecoratorImplT,
typename... ArrayTs>
711 VISKORES_CONT ArrayHandleDecorator<typename std::decay<DecoratorImplT>::type,
712 typename std::decay<ArrayTs>::type...>
717 "Must specify at least one source array handle for "
718 "ArrayHandleDecorator. Consider using "
719 "ArrayHandleImplicit instead.");
721 "Trailing template parameters for "
722 "ArrayHandleDecorator must be a list of ArrayHandle "
725 return { numValues, std::forward<DecoratorImplT>(f), std::forward<ArrayTs>(arrays)... };
730 #ifdef VISKORES_USE_TAO_SEQ
731 #undef VISKORES_USE_TAO_SEQ
734 #endif //viskores_ArrayHandleDecorator_h