VTK-m  2.0
ArrayCopy.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_ArrayCopy_h
11 #define vtk_m_cont_ArrayCopy_h
12 
20 
21 #include <vtkm/cont/vtkm_cont_export.h>
22 
24 
25 #include <vtkm/StaticAssert.h>
26 #include <vtkm/VecTraits.h>
27 
28 namespace vtkm
29 {
30 namespace cont
31 {
32 
33 namespace detail
34 {
35 
36 // Compile-time check to make sure that an `ArrayHandle` passed to `ArrayCopy`
37 // can be passed to a `UnknownArrayHandle`. This function does nothing
38 // except provide a compile error that is easier to understand than if you
39 // let it go and error in `UnknownArrayHandle`. (Huh? I'm not using that.)
40 template <typename T>
41 inline void ArrayCopyValueTypeCheck()
42 {
44  "An `ArrayHandle` that has a special value type that is not supported "
45  "by the precompiled version of `ArrayCopy` has been used. If this array "
46  "must be deep copied, consider using `ArrayCopyDevice`. Look at the "
47  "compile error for the type assigned to template parameter `T` to "
48  "see the offending type.");
49 }
50 
51 template <typename S>
52 struct ArrayCopyConcreteSrc;
53 
54 template <typename SrcIsArrayHandle>
55 inline void ArrayCopyImpl(const vtkm::cont::UnknownArrayHandle& source,
56  vtkm::cont::UnknownArrayHandle& destination,
57  SrcIsArrayHandle,
58  std::false_type)
59 {
60  destination.DeepCopyFrom(source);
61 }
62 template <typename SrcIsArrayHandle>
63 inline void ArrayCopyImpl(const vtkm::cont::UnknownArrayHandle& source,
64  const vtkm::cont::UnknownArrayHandle& destination,
65  SrcIsArrayHandle,
66  std::false_type)
67 {
68  destination.DeepCopyFrom(source);
69 }
70 
71 template <typename T, typename S>
72 void ArrayCopyImpl(const vtkm::cont::UnknownArrayHandle& source,
73  vtkm::cont::ArrayHandle<T, S>& destination,
74  std::false_type,
75  std::true_type)
76 {
77  detail::ArrayCopyValueTypeCheck<T>();
78 
79  using DestType = vtkm::cont::ArrayHandle<T, S>;
80  if (source.CanConvert<DestType>())
81  {
82  destination.DeepCopyFrom(source.AsArrayHandle<DestType>());
83  }
84  else
85  {
86  vtkm::cont::UnknownArrayHandle destWrapper(destination);
87  vtkm::cont::detail::ArrayCopyImpl(source, destWrapper, std::false_type{}, std::false_type{});
88  // Destination array should not change, but just in case.
89  destWrapper.AsArrayHandle(destination);
90  }
91 }
92 
93 template <typename TS, typename SS, typename TD, typename SD>
94 void ArrayCopyImpl(const vtkm::cont::ArrayHandle<TS, SS>& source,
96  std::true_type,
97  std::true_type)
98 {
99  ArrayCopyValueTypeCheck<TS>();
100  ArrayCopyValueTypeCheck<TD>();
101 
102  detail::ArrayCopyConcreteSrc<SS>{}(source, destination);
103 }
104 
105 // Special case of copying data when type is the same.
106 template <typename T, typename S>
107 void ArrayCopyImpl(const vtkm::cont::ArrayHandle<T, S>& source,
108  vtkm::cont::ArrayHandle<T, S>& destination,
109  std::true_type,
110  std::true_type)
111 {
112  destination.DeepCopyFrom(source);
113 }
114 
115 }
116 
141 template <typename SourceArrayType, typename DestArrayType>
142 inline void ArrayCopy(const SourceArrayType& source, DestArrayType& destination)
143 {
144  detail::ArrayCopyImpl(source,
145  destination,
146  typename internal::ArrayHandleCheck<SourceArrayType>::type{},
147  typename internal::ArrayHandleCheck<DestArrayType>::type{});
148 }
149 
150 // Special case where we allow a const UnknownArrayHandle as output.
151 template <typename SourceArrayType>
152 inline void ArrayCopy(const SourceArrayType& source, vtkm::cont::UnknownArrayHandle& destination)
153 {
154  detail::ArrayCopyImpl(source,
155  destination,
156  typename internal::ArrayHandleCheck<SourceArrayType>::type{},
157  std::false_type{});
158 }
159 
160 // Invalid const ArrayHandle in destination, which is not allowed because it will
161 // not work in all cases.
162 template <typename T, typename S>
164 {
165  VTKM_STATIC_ASSERT_MSG(sizeof(T) == 0, "Copying to a constant ArrayHandle is not allowed.");
166 }
167 
169 
181 template <typename T, typename S>
183  vtkm::cont::ArrayHandle<T, S>& destination)
184 {
185  using DestType = vtkm::cont::ArrayHandle<T, S>;
186  if (source.CanConvert<DestType>())
187  {
188  source.AsArrayHandle(destination);
189  }
190  else
191  {
192  vtkm::cont::UnknownArrayHandle destWrapper(destination);
193  vtkm::cont::ArrayCopy(source, destWrapper);
194  // Destination array should not change, but just in case.
195  destWrapper.AsArrayHandle(destination);
196  }
197 }
198 
199 namespace detail
200 {
201 
202 template <typename S>
203 struct ArrayCopyConcreteSrc
204 {
205  template <typename T, typename DestArray>
206  void operator()(const vtkm::cont::ArrayHandle<T, S>& source, DestArray& destination) const
207  {
208  using ArrayType = vtkm::cont::ArrayHandle<T, S>;
209  this->DoIt(
210  source, destination, vtkm::cont::internal::ArrayExtractComponentIsInefficient<ArrayType>{});
211  }
212 
213  template <typename T, typename DestArray>
214  void DoIt(const vtkm::cont::ArrayHandle<T, S>& source,
215  DestArray& destination,
216  std::false_type vtkmNotUsed(isInefficient)) const
217  {
219  }
220 
221  template <typename T, typename DestArray>
222  void DoIt(const vtkm::cont::ArrayHandle<T, S>& source,
223  DestArray& destination,
224  std::true_type vtkmNotUsed(isInefficient)) const
225  {
227  "Attempting to copy from an array of type " +
229  " with ArrayCopy is inefficient. It is highly recommended you use another method "
230  "such as vtkm::cont::ArrayCopyDevice.");
231  // Still call the precompiled `ArrayCopy`. You will get another warning after this,
232  // but it will still technically work, albiet slowly.
234  }
235 };
236 
237 // Special case for constant arrays to be efficient.
238 template <>
239 struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagConstant>
240 {
241  template <typename T1, typename T2, typename S2>
243  vtkm::cont::ArrayHandle<T2, S2>& destination) const
244  {
245  vtkm::cont::ArrayHandleConstant<T1> source = source_;
246  destination.AllocateAndFill(source.GetNumberOfValues(), static_cast<T2>(source.GetValue()));
247  }
248 };
249 
250 // Special case for ArrayHandleIndex to be efficient.
251 template <>
252 struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagIndex>
253 {
254  template <typename T, typename S>
255  void operator()(const vtkm::cont::ArrayHandleIndex& source,
256  vtkm::cont::ArrayHandle<T, S>& destination) const
257  {
258  // Skip warning about inefficient copy because there is a special case in ArrayCopyUnknown.cxx
259  // to copy ArrayHandleIndex efficiently.
261  }
262 };
263 
264 // Special case for ArrayHandleCounting to be efficient.
265 template <>
266 struct VTKM_CONT_EXPORT ArrayCopyConcreteSrc<vtkm::cont::StorageTagCounting>
267 {
268  template <typename T1, typename T2, typename S2>
270  vtkm::cont::ArrayHandle<T2, S2>& destination) const
271  {
272  vtkm::cont::ArrayHandleCounting<T1> countingSource = source;
273  T1 start = countingSource.GetStart();
274  T1 step = countingSource.GetStep();
275  vtkm::Id size = countingSource.GetNumberOfValues();
276  destination.Allocate(size);
277  vtkm::cont::UnknownArrayHandle unknownDest = destination;
278 
279  using VTraits1 = vtkm::VecTraits<T1>;
280  using VTraits2 = vtkm::VecTraits<T2>;
281  for (vtkm::IdComponent comp = 0; comp < VTraits1::GetNumberOfComponents(start); ++comp)
282  {
283  this->CopyCountingFloat(
284  static_cast<vtkm::FloatDefault>(VTraits1::GetComponent(start, comp)),
285  static_cast<vtkm::FloatDefault>(VTraits1::GetComponent(step, comp)),
286  size,
287  unknownDest.ExtractComponent<typename VTraits2::BaseComponentType>(comp));
288  }
289  }
290 
292  vtkm::cont::ArrayHandle<vtkm::Id>& destination) const
293  {
294  destination = this->CopyCountingId(source);
295  }
296 
297 private:
298  void CopyCountingFloat(vtkm::FloatDefault start,
299  vtkm::FloatDefault step,
300  vtkm::Id size,
301  const vtkm::cont::UnknownArrayHandle& result) const;
302  vtkm::cont::ArrayHandle<Id> CopyCountingId(
303  const vtkm::cont::ArrayHandleCounting<vtkm::Id>& source) const;
304 };
305 
306 // Special case for ArrayHandleConcatenate to be efficient
307 template <typename ST1, typename ST2>
308 struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagConcatenate<ST1, ST2>>
309 {
310  template <typename SourceArrayType, typename DestArrayType>
311  void operator()(const SourceArrayType& source, DestArrayType& destination) const
312  {
313  auto source1 = source.GetStorage().GetArray1(source.GetBuffers());
314  auto source2 = source.GetStorage().GetArray2(source.GetBuffers());
315 
316  // Need to preallocate because view decorator will not be able to resize.
317  destination.Allocate(source.GetNumberOfValues());
318  auto dest1 = vtkm::cont::make_ArrayHandleView(destination, 0, source1.GetNumberOfValues());
320  destination, source1.GetNumberOfValues(), source2.GetNumberOfValues());
321 
322  vtkm::cont::ArrayCopy(source1, dest1);
323  vtkm::cont::ArrayCopy(source2, dest2);
324  }
325 };
326 
327 // Special case for ArrayHandlePermutation to be efficient
328 template <typename SIndex, typename SValue>
329 struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagPermutation<SIndex, SValue>>
330 {
331  using SourceStorageTag = vtkm::cont::StorageTagPermutation<SIndex, SValue>;
332  template <typename T1, typename T2, typename S2>
333  void operator()(const vtkm::cont::ArrayHandle<T1, SourceStorageTag>& source,
334  vtkm::cont::ArrayHandle<T2, S2>& destination) const
335  {
336  auto indexArray = source.GetStorage().GetIndexArray(source.GetBuffers());
337  auto valueArray = source.GetStorage().GetValueArray(source.GetBuffers());
339  vtkm::cont::internal::MapArrayPermutation(valueArray, indexArray);
340  vtkm::cont::ArrayCopyShallowIfPossible(copy, destination);
341  }
342 };
343 
344 } // namespace detail
345 
346 } // namespace cont
347 } // namespace vtkm
348 
349 #endif //vtk_m_cont_ArrayCopy_h
ArrayHandleConcatenate.h
vtkm::cont::ArrayHandle::GetBuffers
const VTKM_CONT std::vector< vtkm::cont::internal::Buffer > & GetBuffers() const
Returns the internal Buffer structures that hold the data.
Definition: ArrayHandle.h:696
vtkm::cont::ArrayHandleCounting::GetStart
VTKM_CONT CountingValueType GetStart() const
Definition: ArrayHandleCounting.h:142
vtkm::cont::ArrayHandle< T, vtkm::cont::StorageTagConstant >::GetNumberOfValues
VTKM_CONT vtkm::Id GetNumberOfValues() const
Returns the number of entries in the array.
Definition: ArrayHandle.h:448
vtkm::cont::ArrayHandle< T, S >
vtkm::cont::UnknownArrayHandle::AsArrayHandle
VTKM_CONT void AsArrayHandle(vtkm::cont::ArrayHandle< T, S > &array) const
Definition: UnknownArrayHandle.h:616
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::cont::make_ArrayHandleView
ArrayHandleView< ArrayHandleType > make_ArrayHandleView(const ArrayHandleType &array, vtkm::Id startIndex, vtkm::Id numValues)
Definition: ArrayHandleView.h:222
vtkm::cont::LogLevel::Warn
@ Warn
Less important user errors, such as out-of-bounds parameters.
vtkm::cont::UnknownArrayHandle::ExtractComponent
VTKM_CONT vtkm::cont::ArrayHandleStride< BaseComponentType > ExtractComponent(vtkm::IdComponent componentIndex, vtkm::CopyFlag allowCopy=vtkm::CopyFlag::On) const
Extract a component of the array.
Definition: UnknownArrayHandle.h:730
vtkm::cont::ArrayHandle::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::cont::ArrayHandle::AllocateAndFill
VTKM_CONT void AllocateAndFill(vtkm::Id numberOfValues, const ValueType &fillValue, vtkm::CopyFlag preserve, vtkm::cont::Token &token) const
Allocates an array and fills it with an initial value.
Definition: ArrayHandle.h:495
vtkm::cont::ArrayHandleConstant::GetValue
VTKM_CONT T GetValue() const
Returns the constant value stored in this array.
Definition: ArrayHandleConstant.h:81
vtkm::IdComponent
vtkm::Int32 IdComponent
Represents a component ID (index of component in a vector).
Definition: Types.h:168
vtkm::cont::ArrayCopyShallowIfPossible
VTKM_CONT void ArrayCopyShallowIfPossible(const vtkm::cont::UnknownArrayHandle source, vtkm::cont::ArrayHandle< T, S > &destination)
Copies from an unknown to a known array type.
Definition: ArrayCopy.h:182
vtkm::cont::UnknownArrayHandle::CanConvert
VTKM_CONT bool CanConvert() const
Determine if the contained array can be passed to the given array type.
Definition: UnknownArrayHandle.h:913
vtkm::cont::UnknownArrayHandle
An ArrayHandle of an unknown value type and storage.
Definition: UnknownArrayHandle.h:406
vtkm::HasVecTraits
typename detail::HasVecTraitsImpl< T >::Type HasVecTraits
Determines whether the given type has VecTraits defined.
Definition: VecTraits.h:176
ArrayHandleConstant.h
vtkm::cont::ArrayHandle::GetStorage
VTKM_CONT StorageType GetStorage() const
Get the storage.
Definition: ArrayHandle.h:401
vtkm::cont::StorageTagPermutation
Definition: ArrayHandlePermutation.h:93
ArrayHandleView.h
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::cont::UnknownArrayHandle::DeepCopyFrom
void DeepCopyFrom(const vtkm::cont::UnknownArrayHandle &source)
Deep copies data from another UnknownArrayHandle.
UnknownArrayHandle.h
ArrayHandlePermutation.h
MapArrayPermutation.h
ArrayHandleIndex.h
vtkm::cont::ArrayHandleCounting
ArrayHandleCounting is a specialization of ArrayHandle.
Definition: ArrayHandleCounting.h:127
VTKM_STATIC_ASSERT_MSG
#define VTKM_STATIC_ASSERT_MSG(condition, message)
Definition: StaticAssert.h:18
vtkm::cont::ArrayCopy
void ArrayCopy(const SourceArrayType &source, DestArrayType &destination)
Does a deep copy from one array to another array.
Definition: ArrayCopy.h:142
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::cont::ArrayHandleConstant
An array handle with a constant value.
Definition: ArrayHandleConstant.h:63
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::cont::ArrayHandle::DeepCopyFrom
VTKM_CONT void DeepCopyFrom(const vtkm::cont::ArrayHandle< ValueType, StorageTag > &source) const
Deep copies the data in the array.
Definition: ArrayHandle.h:682
vtkm::FloatDefault
vtkm::Float32 FloatDefault
The floating point type to use when no other precision is specified.
Definition: Types.h:198
StaticAssert.h
ArrayHandleCounting.h
vtkm::VecTraits
The VecTraits class gives several static members that define how to use a given type as a vector.
Definition: VecTraits.h:66
vtkm::cont::ArrayHandleCounting::GetStep
VTKM_CONT CountingValueType GetStep() const
Definition: ArrayHandleCounting.h:144
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
vtkm::cont::ArrayHandleIndex
An implicit array handle containing the its own indices.
Definition: ArrayHandleIndex.h:54