VTK-m  2.0
ArrayExtractComponent.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_ArrayExtractComponent_h
11 #define vtk_m_cont_ArrayExtractComponent_h
12 
16 #include <vtkm/cont/Logging.h>
17 
18 #include <vtkm/TypeTraits.h>
19 #include <vtkm/VecFlat.h>
20 #include <vtkm/VecTraits.h>
21 
22 #include <vtkmstd/integer_sequence.h>
23 
24 #include <vtkm/cont/vtkm_cont_export.h>
25 
26 namespace vtkm
27 {
28 namespace cont
29 {
30 
31 namespace internal
32 {
33 
34 // Note: Using partial template specialization instead of function overloading to
35 // specialize ArrayExtractComponent for different types of array handles. This is
36 // because function overloading from a templated function is done when the template
37 // is defined rather than where it is resolved. This causes problems when extracting
38 // components of, say, an ArrayHandleMultiplexer holding an ArrayHandleSOA.
39 template <typename T, typename S>
41 ArrayExtractComponentFallback(const vtkm::cont::ArrayHandle<T, S>& src,
42  vtkm::IdComponent componentIndex,
43  vtkm::CopyFlag allowCopy)
44 {
45  if (allowCopy != vtkm::CopyFlag::On)
46  {
47  throw vtkm::cont::ErrorBadValue("Cannot extract component of " +
49  " without copying");
50  }
52  "Extracting component " << componentIndex << " of "
54  << " requires an inefficient memory copy.");
55 
56  using BaseComponentType = typename vtkm::internal::SafeVecTraits<T>::BaseComponentType;
57  vtkm::Id numValues = src.GetNumberOfValues();
59  dest.Allocate(numValues);
60  auto srcPortal = src.ReadPortal();
61  auto destPortal = dest.WritePortal();
62  for (vtkm::Id arrayIndex = 0; arrayIndex < numValues; ++arrayIndex)
63  {
64  destPortal.Set(arrayIndex,
65  vtkm::internal::GetFlatVecComponent(srcPortal.Get(arrayIndex), componentIndex));
66  }
67 
68  return vtkm::cont::ArrayHandleStride<BaseComponentType>(dest, numValues, 1, 0);
69 }
70 
71 // Used as a superclass for ArrayHandleComponentImpls that are inefficient (and should be
72 // avoided).
73 struct ArrayExtractComponentImplInefficient
74 {
75 };
76 
77 template <typename S>
78 struct ArrayExtractComponentImpl : ArrayExtractComponentImplInefficient
79 {
80  template <typename T>
82  operator()(const vtkm::cont::ArrayHandle<T, S>& src,
83  vtkm::IdComponent componentIndex,
84  vtkm::CopyFlag allowCopy) const
85  {
86  // This is the slow "default" implementation. ArrayHandle implementations should provide
87  // more efficient overloads where applicable.
88  return vtkm::cont::internal::ArrayExtractComponentFallback(src, componentIndex, allowCopy);
89  }
90 };
91 
92 template <>
93 struct ArrayExtractComponentImpl<vtkm::cont::StorageTagStride>
94 {
95  template <typename T>
98  vtkm::IdComponent componentIndex,
99  vtkm::CopyFlag allowCopy) const
100  {
101  return this->DoExtract(src,
102  componentIndex,
103  allowCopy,
104  typename vtkm::internal::SafeVecTraits<T>::HasMultipleComponents{});
105  }
106 
107 private:
108  template <typename T>
110  vtkm::IdComponent componentIndex,
111  vtkm::CopyFlag vtkmNotUsed(allowCopy),
113  {
114  VTKM_ASSERT(componentIndex == 0);
115  using VTraits = vtkm::internal::SafeVecTraits<T>;
116  using TBase = typename VTraits::BaseComponentType;
117  VTKM_STATIC_ASSERT(VTraits::NUM_COMPONENTS == 1);
118 
120 
121  // Note, we are initializing the result in this strange way for cases where type
122  // T has a single component but does not equal its own BaseComponentType. A vtkm::Vec
123  // of size 1 fits into this category.
124  return vtkm::cont::ArrayHandleStride<TBase>(array.GetBuffers()[1],
125  array.GetNumberOfValues(),
126  array.GetStride(),
127  array.GetOffset(),
128  array.GetModulo(),
129  array.GetDivisor());
130  }
131 
132  template <typename VecType>
134  vtkm::IdComponent componentIndex,
135  vtkm::CopyFlag allowCopy,
137  {
138  using VTraits = vtkm::internal::SafeVecTraits<VecType>;
139  using T = typename VTraits::ComponentType;
140  constexpr vtkm::IdComponent N = VTraits::NUM_COMPONENTS;
141 
142  constexpr vtkm::IdComponent subStride = vtkm::internal::TotalNumComponents<T>::value;
144  vtkm::cont::ArrayHandleStride<T> tmpIn(array.GetBuffers()[1],
145  array.GetNumberOfValues(),
146  array.GetStride() * N,
147  (array.GetOffset() * N) + (componentIndex / subStride),
148  array.GetModulo() * N,
149  array.GetDivisor());
150  return (*this)(tmpIn, componentIndex % subStride, allowCopy);
151  }
152 };
153 
154 template <>
155 struct ArrayExtractComponentImpl<vtkm::cont::StorageTagBasic>
156 {
157  template <typename T>
159  vtkm::IdComponent componentIndex,
160  vtkm::CopyFlag allowCopy) const
161  -> decltype(
162  ArrayExtractComponentImpl<vtkm::cont::StorageTagStride>{}(vtkm::cont::ArrayHandleStride<T>{},
163  componentIndex,
164  allowCopy))
165  {
166  return ArrayExtractComponentImpl<vtkm::cont::StorageTagStride>{}(
168  componentIndex,
169  allowCopy);
170  }
171 };
172 
173 namespace detail
174 {
175 
176 template <std::size_t, typename Super>
177 struct ForwardSuper : Super
178 {
179 };
180 
181 template <typename sequence, typename... Supers>
182 struct SharedSupersImpl;
183 
184 template <std::size_t... Indices, typename... Supers>
185 struct SharedSupersImpl<vtkmstd::index_sequence<Indices...>, Supers...>
186  : ForwardSuper<Indices, Supers>...
187 {
188 };
189 
190 } // namespace detail
191 
192 // `ArrayExtractComponentImpl`s that modify the behavior from other storage types might
193 // want to inherit from the `ArrayExtractComponentImpl`s of these storage types. However,
194 // if the template specifies multiple storage types, two of the same might be specified,
195 // and it is illegal in C++ to directly inherit from the same type twice. This special
196 // superclass accepts a variable amout of superclasses. Inheriting from this will inherit
197 // from all these superclasses, and duplicates are allowed.
198 template <typename... Supers>
199 using DuplicatedSuperclasses =
200  detail::SharedSupersImpl<vtkmstd::make_index_sequence<sizeof...(Supers)>, Supers...>;
201 
202 template <typename... StorageTags>
203 using ArrayExtractComponentImplInherit =
204  DuplicatedSuperclasses<vtkm::cont::internal::ArrayExtractComponentImpl<StorageTags>...>;
205 
208 template <typename ArrayHandleType>
209 using ArrayExtractComponentIsInefficient = typename std::is_base_of<
210  vtkm::cont::internal::ArrayExtractComponentImplInefficient,
211  vtkm::cont::internal::ArrayExtractComponentImpl<typename ArrayHandleType::StorageTag>>::type;
212 
213 } // namespace internal
214 
256 template <typename T, typename S>
259  vtkm::IdComponent componentIndex,
261 {
262  return internal::ArrayExtractComponentImpl<S>{}(src, componentIndex, allowCopy);
263 }
264 
265 }
266 } // namespace vtkm::cont
267 
268 #endif //vtk_m_cont_ArrayExtractComponent_h
VecFlat.h
vtkm::cont::ArrayHandle::GetNumberOfValues
VTKM_CONT vtkm::Id GetNumberOfValues() const
Returns the number of entries in the array.
Definition: ArrayHandle.h:448
vtkm::cont::ArrayHandle< T, S >
ArrayHandleStride.h
vtkm::VecTraitsTagMultipleComponents
A tag for vectors that are "true" vectors (i.e.
Definition: VecTraits.h:21
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::cont::LogLevel::Warn
@ Warn
Less important user errors, such as out-of-bounds parameters.
VTKM_ASSERT
#define VTKM_ASSERT(condition)
Definition: Assert.h:43
vtkm::cont::ArrayHandle< T, vtkm::cont::StorageTagBasic >::Allocate
VTKM_CONT void Allocate(vtkm::Id numberOfValues, vtkm::CopyFlag preserve, vtkm::cont::Token &token) const
Allocates an array large enough to hold the given number of values.
Definition: ArrayHandle.h:465
vtkm::IdComponent
vtkm::Int32 IdComponent
Represents a component ID (index of component in a vector).
Definition: Types.h:168
ArrayHandleBasic.h
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::cont::ArrayHandleStride
An ArrayHandle that accesses a basic array with strides and offsets.
Definition: ArrayHandleStride.h:251
TypeTraits.h
VTKM_STATIC_ASSERT
#define VTKM_STATIC_ASSERT(condition)
Definition: StaticAssert.h:16
vtkm::cont::ArrayHandle< T, vtkm::cont::StorageTagBasic >::WritePortal
VTKM_CONT WritePortalType WritePortal() const
Get an array portal that can be used in the control environment.
Definition: ArrayHandle.h:435
vtkm::CopyFlag::On
@ On
vtkmNotUsed
#define vtkmNotUsed(parameter_name)
Simple macro to identify a parameter as unused.
Definition: ExportMacros.h:128
VTKM_LOG_S
#define VTKM_LOG_S(level,...)
Writes a message using stream syntax to the indicated log level.
Definition: Logging.h:261
vtkm::VecTraitsTagSingleComponent
A tag for vectors that are really just scalars (i.e.
Definition: VecTraits.h:28
vtkm::cont::ErrorBadValue
This class is thrown when a VTKm function or method encounters an invalid value that inhibits progres...
Definition: ErrorBadValue.h:25
vtkm::cont::ArrayHandle::ReadPortal
VTKM_CONT ReadPortalType ReadPortal() const
Get an array portal that can be used in the control environment.
Definition: ArrayHandle.h:414
ErrorBadValue.h
vtkm::cont::ArrayExtractComponent
vtkm::cont::ArrayHandleStride< typename vtkm::internal::SafeVecTraits< 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:258
vtkm::CopyFlag
CopyFlag
Definition: Flags.h:16
vtkm::cont::ArrayHandleBasic
Definition: ArrayHandleBasic.h:97
Logging.h
Logging utilities.
vtkm::cont::TypeToString
VTKM_CONT_EXPORT VTKM_CONT std::string TypeToString(const std::type_info &t)
Use RTTI information to retrieve the name of the type T.
VecTraits.h