Viskores  1.0
ArrayExtractComponent.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_ArrayExtractComponent_h
19 #define viskores_cont_ArrayExtractComponent_h
20 
24 #include <viskores/cont/Logging.h>
25 
26 #include <viskores/TypeTraits.h>
27 #include <viskores/VecFlat.h>
28 #include <viskores/VecTraits.h>
29 
30 #include <viskoresstd/integer_sequence.h>
31 
33 
34 namespace viskores
35 {
36 namespace cont
37 {
38 
39 namespace internal
40 {
41 
42 // Note: Using partial template specialization instead of function overloading to
43 // specialize ArrayExtractComponent for different types of array handles. This is
44 // because function overloading from a templated function is done when the template
45 // is defined rather than where it is resolved. This causes problems when extracting
46 // components of, say, an ArrayHandleMultiplexer holding an ArrayHandleSOA.
47 template <typename T, typename S>
49 ArrayExtractComponentFallback(const viskores::cont::ArrayHandle<T, S>& src,
50  viskores::IdComponent componentIndex,
51  viskores::CopyFlag allowCopy)
52 {
53  if (allowCopy != viskores::CopyFlag::On)
54  {
56  "Cannot extract component of " +
58  }
60  "Extracting component "
61  << componentIndex << " of "
63  << " requires an inefficient memory copy.");
64 
65  using BaseComponentType = typename viskores::VecTraits<T>::BaseComponentType;
66  viskores::Id numValues = src.GetNumberOfValues();
68  dest.Allocate(numValues);
69  auto srcPortal = src.ReadPortal();
70  auto destPortal = dest.WritePortal();
71  for (viskores::Id arrayIndex = 0; arrayIndex < numValues; ++arrayIndex)
72  {
73  destPortal.Set(
74  arrayIndex,
75  viskores::internal::GetFlatVecComponent(srcPortal.Get(arrayIndex), componentIndex));
76  }
77 
78  return viskores::cont::ArrayHandleStride<BaseComponentType>(dest, numValues, 1, 0);
79 }
80 
81 // Used as a superclass for ArrayHandleComponentImpls that are inefficient (and should be
82 // avoided).
83 struct ArrayExtractComponentImplInefficient
84 {
85 };
86 
87 template <typename S>
88 struct ArrayExtractComponentImpl : ArrayExtractComponentImplInefficient
89 {
90  template <typename T>
93  viskores::IdComponent componentIndex,
94  viskores::CopyFlag allowCopy) const
95  {
96  // This is the slow "default" implementation. ArrayHandle implementations should provide
97  // more efficient overloads where applicable.
98  return viskores::cont::internal::ArrayExtractComponentFallback(src, componentIndex, allowCopy);
99  }
100 };
101 
102 template <>
103 struct ArrayExtractComponentImpl<viskores::cont::StorageTagStride>
104 {
105  template <typename T>
108  viskores::IdComponent componentIndex,
109  viskores::CopyFlag allowCopy) const
110  {
111  return this->DoExtract(
112  src, componentIndex, allowCopy, typename viskores::VecTraits<T>::HasMultipleComponents{});
113  }
114 
115 private:
116  template <typename T>
118  viskores::IdComponent componentIndex,
121  {
122  VISKORES_ASSERT(componentIndex == 0);
123  using VTraits = viskores::VecTraits<T>;
124  using TBase = typename VTraits::BaseComponentType;
125  VISKORES_STATIC_ASSERT(VTraits::NUM_COMPONENTS == 1);
126 
128 
129  // Note, we are initializing the result in this strange way for cases where type
130  // T has a single component but does not equal its own BaseComponentType. A viskores::Vec
131  // of size 1 fits into this category.
132  return viskores::cont::ArrayHandleStride<TBase>(array.GetBuffers()[1],
133  array.GetNumberOfValues(),
134  array.GetStride(),
135  array.GetOffset(),
136  array.GetModulo(),
137  array.GetDivisor());
138  }
139 
140  template <typename VecType>
142  viskores::IdComponent componentIndex,
143  viskores::CopyFlag allowCopy,
145  {
146  using VTraits = viskores::VecTraits<VecType>;
147  using T = typename VTraits::ComponentType;
148  constexpr viskores::IdComponent N = VTraits::NUM_COMPONENTS;
149 
150  constexpr viskores::IdComponent subStride = viskores::internal::TotalNumComponents<T>::value;
152  viskores::cont::ArrayHandleStride<T> tmpIn(array.GetBuffers()[1],
153  array.GetNumberOfValues(),
154  array.GetStride() * N,
155  (array.GetOffset() * N) +
156  (componentIndex / subStride),
157  array.GetModulo() * N,
158  array.GetDivisor());
159  return (*this)(tmpIn, componentIndex % subStride, allowCopy);
160  }
161 };
162 
163 template <>
164 struct ArrayExtractComponentImpl<viskores::cont::StorageTagBasic>
165 {
166  template <typename T>
168  viskores::IdComponent componentIndex,
169  viskores::CopyFlag allowCopy) const
170  -> decltype(ArrayExtractComponentImpl<viskores::cont::StorageTagStride>{}(
172  componentIndex,
173  allowCopy))
174  {
175  return ArrayExtractComponentImpl<viskores::cont::StorageTagStride>{}(
177  componentIndex,
178  allowCopy);
179  }
180 };
181 
182 namespace detail
183 {
184 
185 template <std::size_t, typename Super>
186 struct ForwardSuper : Super
187 {
188 };
189 
190 template <typename sequence, typename... Supers>
191 struct SharedSupersImpl;
192 
193 template <std::size_t... Indices, typename... Supers>
194 struct SharedSupersImpl<viskoresstd::index_sequence<Indices...>, Supers...>
195  : ForwardSuper<Indices, Supers>...
196 {
197 };
198 
199 } // namespace detail
200 
201 // `ArrayExtractComponentImpl`s that modify the behavior from other storage types might
202 // want to inherit from the `ArrayExtractComponentImpl`s of these storage types. However,
203 // if the template specifies multiple storage types, two of the same might be specified,
204 // and it is illegal in C++ to directly inherit from the same type twice. This special
205 // superclass accepts a variable amout of superclasses. Inheriting from this will inherit
206 // from all these superclasses, and duplicates are allowed.
207 template <typename... Supers>
208 using DuplicatedSuperclasses =
209  detail::SharedSupersImpl<viskoresstd::make_index_sequence<sizeof...(Supers)>, Supers...>;
210 
211 template <typename... StorageTags>
212 using ArrayExtractComponentImplInherit =
213  DuplicatedSuperclasses<viskores::cont::internal::ArrayExtractComponentImpl<StorageTags>...>;
214 
217 template <typename ArrayHandleType>
218 using ArrayExtractComponentIsInefficient = typename std::is_base_of<
219  viskores::cont::internal::ArrayExtractComponentImplInefficient,
220  viskores::cont::internal::ArrayExtractComponentImpl<typename ArrayHandleType::StorageTag>>::type;
221 
222 } // namespace internal
223 
265 template <typename T, typename S>
268  viskores::IdComponent componentIndex,
270 {
271  return internal::ArrayExtractComponentImpl<S>{}(src, componentIndex, allowCopy);
272 }
273 
274 }
275 } // namespace viskores::cont
276 
277 #endif //viskores_cont_ArrayExtractComponent_h
VecFlat.h
viskores::cont::ArrayHandle::ReadPortal
ReadPortalType ReadPortal() const
Get an array portal that can be used in the control environment.
Definition: ArrayHandle.h:447
ArrayHandleStride.h
viskores::cont::LogLevel::Warn
@ Warn
Less important user errors, such as out-of-bounds parameters.
viskoresNotUsed
#define viskoresNotUsed(parameter_name)
Simple macro to identify a parameter as unused.
Definition: ExportMacros.h:136
ArrayHandleBasic.h
viskores::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:313
viskores::VecTraitsTagMultipleComponents
A tag for vectors that are "true" vectors (i.e.
Definition: VecTraits.h:31
viskores::VecTraitsTagSingleComponent
A tag for vectors that are really just scalars (i.e.
Definition: VecTraits.h:38
viskores::IdComponent
viskores::Int32 IdComponent
Base type to use to index small lists.
Definition: Types.h:202
viskores::cont::ArrayHandleStride
An ArrayHandle that accesses a basic array with strides and offsets.
Definition: ArrayHandleStride.h:343
TypeTraits.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::Id
viskores::Int64 Id
Base type to use to index arrays.
Definition: Types.h:235
viskores
Groups connected points that have the same field value.
Definition: Atomic.h:27
viskores::CopyFlag::On
@ On
viskores::VecTraits
Traits that can be queried to treat any type as a Vec.
Definition: VecTraits.h:69
viskores::cont::ArrayHandle< T, viskores::cont::StorageTagBasic >::Allocate
void Allocate(viskores::Id numberOfValues, viskores::CopyFlag preserve, viskores::cont::Token &token) const
Allocates an array large enough to hold the given number of values.
Definition: ArrayHandle.h:504
viskores::cont::ArrayHandleBasic
Basic array storage for an array handle.
Definition: ArrayHandleBasic.h:120
viskores::cont::ArrayHandle::GetNumberOfValues
viskores::Id GetNumberOfValues() const
Returns the number of entries in the array.
Definition: ArrayHandle.h:482
VISKORES_ASSERT
#define VISKORES_ASSERT(condition)
Definition: Assert.h:51
viskores::cont::ArrayHandle< T, viskores::cont::StorageTagBasic >::WritePortal
WritePortalType WritePortal() const
Get an array portal that can be used in the control environment.
Definition: ArrayHandle.h:468
viskores::cont::ErrorBadValue
This class is thrown when a Viskores function or method encounters an invalid value that inhibits pro...
Definition: ErrorBadValue.h:33
VISKORES_LOG_S
#define VISKORES_LOG_S(level,...)
Writes a message using stream syntax to the indicated log level.
Definition: Logging.h:216
ErrorBadValue.h
viskores::VecTraits::BaseComponentType
T BaseComponentType
Base component type in the vector.
Definition: VecTraits.h:86
Logging.h
Logging utilities.
viskores::CopyFlag
CopyFlag
Identifier used to specify whether a function should deep copy data.
Definition: Flags.h:25
VecTraits.h
viskores::cont::TypeToString
std::string TypeToString(const std::type_info &t)
Use RTTI information to retrieve the name of the type T.
VISKORES_STATIC_ASSERT
#define VISKORES_STATIC_ASSERT(condition)
Definition: StaticAssert.h:24
viskores_cont_export.h