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