1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //  This software is distributed WITHOUT ANY WARRANTY; without even
6 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
7 //  PURPOSE.  See the above copyright notice for more information.
8 //
9 //  Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10 //  Copyright 2014 UT-Battelle, LLC.
11 //  Copyright 2014 Los Alamos National Security.
12 //
13 //  Under the terms of Contract DE-NA0003525 with NTESS,
14 //  the U.S. Government retains certain rights in this software.
15 //
16 //  Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
17 //  Laboratory (LANL), the U.S. Government retains certain rights in
18 //  this software.
19 //============================================================================
20 #ifndef vtk_m_VecTraits_h
21 #define vtk_m_VecTraits_h
22 
23 #include <vtkm/Types.h>
24 
25 namespace vtkm
26 {
27 
28 /// A tag for vectors that are "true" vectors (i.e. have more than one
29 /// component).
30 ///
31 struct VecTraitsTagMultipleComponents
32 {
33 };
34 
35 /// A tag for vectors that are really just scalars (i.e. have only one
36 /// component)
37 ///
38 struct VecTraitsTagSingleComponent
39 {
40 };
41 
42 /// A tag for vectors where the number of components are known at compile time.
43 ///
44 struct VecTraitsTagSizeStatic
45 {
46 };
47 
48 /// A tag for vectors where the number of components are not determined until
49 /// run time.
50 ///
51 struct VecTraitsTagSizeVariable
52 {
53 };
54 
55 namespace internal
56 {
57 
58 template <vtkm::IdComponent numComponents>
59 struct VecTraitsMultipleComponentChooser
60 {
61   using Type = vtkm::VecTraitsTagMultipleComponents;
62 };
63 
64 template <>
65 struct VecTraitsMultipleComponentChooser<1>
66 {
67   using Type = vtkm::VecTraitsTagSingleComponent;
68 };
69 
70 } // namespace detail
71 
72 /// The VecTraits class gives several static members that define how
73 /// to use a given type as a vector.
74 ///
75 template <class VecType>
76 struct VecTraits
77 #ifdef VTKM_DOXYGEN_ONLY
78 {
79   /// Type of the components in the vector.
80   ///
81   using ComponentType = typename VecType::ComponentType;
82 
83   /// \brief Number of components in the vector.
84   ///
85   /// This is only defined for vectors of a static size.
86   ///
87   static constexpr vtkm::IdComponent NUM_COMPONENTS = VecType::NUM_COMPONENTS;
88 
89   /// Number of components in the given vector.
90   ///
91   static vtkm::IdComponent GetNumberOfComponents(const VecType& vec);
92 
93   /// \brief A tag specifying whether this vector has multiple components (i.e. is a "real" vector).
94   ///
95   /// This tag can be useful for creating specialized functions when a vector
96   /// is really just a scalar.
97   ///
98   using HasMultipleComponents =
99     typename internal::VecTraitsMultipleComponentChooser<NUM_COMPONENTS>::Type;
100 
101   /// \brief A tag specifying whether the size of this vector is known at compile time.
102   ///
103   /// If set to \c VecTraitsTagSizeStatic, then \c NUM_COMPONENTS is set. If
104   /// set to \c VecTraitsTagSizeVariable, then the number of components is not
105   /// known at compile time and must be queried with \c GetNumberOfComponents.
106   ///
107   using IsSizeStatic = vtkm::VecTraitsTagSizeStatic;
108 
109   /// Returns the value in a given component of the vector.
110   ///
111   VTKM_EXEC_CONT static const ComponentType& GetComponent(
112     const typename std::remove_const<VecType>::type& vector,
113     vtkm::IdComponent component);
114   VTKM_EXEC_CONT static ComponentType& GetComponent(
115     typename std::remove_const<VecType>::type& vector,
116     vtkm::IdComponent component);
117 
118   /// Changes the value in a given component of the vector.
119   ///
120   VTKM_EXEC_CONT static void SetComponent(VecType& vector,
121                                           vtkm::IdComponent component,
122                                           ComponentType value);
123 
124   /// Copies the components in the given vector into a given Vec object.
125   ///
126   template <vktm::IdComponent destSize>
127   VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec<ComponentType, destSize>& dest);
128 };
129 #else  // VTKM_DOXYGEN_ONLY
130   ;
131 #endif // VTKM_DOXYGEN_ONLY
132 
133 // This partial specialization allows you to define a non-const version of
134 // VecTraits and have it still work for const version.
135 //
136 template <typename T>
137 struct VecTraits<const T> : VecTraits<T>
138 {
139 };
140 
141 template <typename T, vtkm::IdComponent Size>
142 struct VecTraits<vtkm::Vec<T, Size>>
143 {
144   using VecType = vtkm::Vec<T, Size>;
145 
146   /// Type of the components in the vector.
147   ///
148   using ComponentType = typename VecType::ComponentType;
149 
150   /// Number of components in the vector.
151   ///
152   static constexpr vtkm::IdComponent NUM_COMPONENTS = VecType::NUM_COMPONENTS;
153 
154   /// Number of components in the given vector.
155   ///
156   VTKM_EXEC_CONT
157   static vtkm::IdComponent GetNumberOfComponents(const VecType&) { return NUM_COMPONENTS; }
158 
159   /// A tag specifying whether this vector has multiple components (i.e. is a
160   /// "real" vector). This tag can be useful for creating specialized functions
161   /// when a vector is really just a scalar.
162   ///
163   using HasMultipleComponents =
164     typename internal::VecTraitsMultipleComponentChooser<NUM_COMPONENTS>::Type;
165 
166   /// A tag specifying whether the size of this vector is known at compile
167   /// time. If set to \c VecTraitsTagSizeStatic, then \c NUM_COMPONENTS is set.
168   /// If set to \c VecTraitsTagSizeVariable, then the number of components is
169   /// not known at compile time and must be queried with \c
170   /// GetNumberOfComponents.
171   ///
172   using IsSizeStatic = vtkm::VecTraitsTagSizeStatic;
173 
174   /// Returns the value in a given component of the vector.
175   ///
176   VTKM_EXEC_CONT
177   static const ComponentType& GetComponent(const VecType& vector, vtkm::IdComponent component)
178   {
179     return vector[component];
180   }
181   VTKM_EXEC_CONT
182   static ComponentType& GetComponent(VecType& vector, vtkm::IdComponent component)
183   {
184     return vector[component];
185   }
186 
187   /// Changes the value in a given component of the vector.
188   ///
189   VTKM_EXEC_CONT static void SetComponent(VecType& vector,
190                                           vtkm::IdComponent component,
191                                           ComponentType value)
192   {
193     vector[component] = value;
194   }
195 
196   /// Converts whatever type this vector is into the standard VTKm Tuple.
197   ///
198   template <vtkm::IdComponent destSize>
199   VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec<ComponentType, destSize>& dest)
200   {
201     src.CopyInto(dest);
202   }
203 };
204 
205 template <typename T>
206 struct VecTraits<vtkm::VecC<T>>
207 {
208   using VecType = vtkm::VecC<T>;
209 
210   /// Type of the components in the vector.
211   ///
212   using ComponentType = typename VecType::ComponentType;
213 
214   /// Number of components in the given vector.
215   ///
216   VTKM_EXEC_CONT
217   static vtkm::IdComponent GetNumberOfComponents(const VecType& vector)
218   {
219     return vector.GetNumberOfComponents();
220   }
221 
222   /// A tag specifying whether this vector has multiple components (i.e. is a
223   /// "real" vector). This tag can be useful for creating specialized functions
224   /// when a vector is really just a scalar.
225   ///
226   /// The size of a \c VecC is not known until runtime and can always
227   /// potentially have multiple components, this is always set to \c
228   /// HasMultipleComponents.
229   ///
230   using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
231 
232   /// A tag specifying whether the size of this vector is known at compile
233   /// time. If set to \c VecTraitsTagSizeStatic, then \c NUM_COMPONENTS is set.
234   /// If set to \c VecTraitsTagSizeVariable, then the number of components is
235   /// not known at compile time and must be queried with \c
236   /// GetNumberOfComponents.
237   ///
238   using IsSizeStatic = vtkm::VecTraitsTagSizeVariable;
239 
240   /// Returns the value in a given component of the vector.
241   ///
242   VTKM_EXEC_CONT
243   static const ComponentType& GetComponent(const VecType& vector, vtkm::IdComponent component)
244   {
245     return vector[component];
246   }
247   VTKM_EXEC_CONT
248   static ComponentType& GetComponent(VecType& vector, vtkm::IdComponent component)
249   {
250     return vector[component];
251   }
252 
253   /// Changes the value in a given component of the vector.
254   ///
255   VTKM_EXEC_CONT
256   static void SetComponent(VecType& vector, vtkm::IdComponent component, ComponentType value)
257   {
258     vector[component] = value;
259   }
260 
261   /// Converts whatever type this vector is into the standard VTKm Tuple.
262   ///
263   template <vtkm::IdComponent destSize>
264   VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec<ComponentType, destSize>& dest)
265   {
266     src.CopyInto(dest);
267   }
268 };
269 
270 template <typename T>
271 struct VecTraits<vtkm::VecCConst<T>>
272 {
273   using VecType = vtkm::VecCConst<T>;
274 
275   /// Type of the components in the vector.
276   ///
277   using ComponentType = typename VecType::ComponentType;
278 
279   /// Number of components in the given vector.
280   ///
281   VTKM_EXEC_CONT
282   static vtkm::IdComponent GetNumberOfComponents(const VecType& vector)
283   {
284     return vector.GetNumberOfComponents();
285   }
286 
287   /// A tag specifying whether this vector has multiple components (i.e. is a
288   /// "real" vector). This tag can be useful for creating specialized functions
289   /// when a vector is really just a scalar.
290   ///
291   /// The size of a \c VecCConst is not known until runtime and can always
292   /// potentially have multiple components, this is always set to \c
293   /// HasMultipleComponents.
294   ///
295   using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
296 
297   /// A tag specifying whether the size of this vector is known at compile
298   /// time. If set to \c VecTraitsTagSizeStatic, then \c NUM_COMPONENTS is set.
299   /// If set to \c VecTraitsTagSizeVariable, then the number of components is
300   /// not known at compile time and must be queried with \c
301   /// GetNumberOfComponents.
302   ///
303   using IsSizeStatic = vtkm::VecTraitsTagSizeVariable;
304 
305   /// Returns the value in a given component of the vector.
306   ///
307   VTKM_EXEC_CONT
308   static const ComponentType& GetComponent(const VecType& vector, vtkm::IdComponent component)
309   {
310     return vector[component];
311   }
312 
313   /// Changes the value in a given component of the vector.
314   ///
315   VTKM_EXEC_CONT
316   static void SetComponent(VecType& vector, vtkm::IdComponent component, ComponentType value)
317   {
318     vector[component] = value;
319   }
320 
321   /// Converts whatever type this vector is into the standard VTKm Tuple.
322   ///
323   template <vtkm::IdComponent destSize>
324   VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec<ComponentType, destSize>& dest)
325   {
326     src.CopyInto(dest);
327   }
328 };
329 
330 namespace internal
331 {
332 /// Used for overriding VecTraits for basic scalar types.
333 ///
334 template <typename ScalarType>
335 struct VecTraitsBasic
336 {
337   using ComponentType = ScalarType;
338   static constexpr vtkm::IdComponent NUM_COMPONENTS = 1;
339   using HasMultipleComponents = vtkm::VecTraitsTagSingleComponent;
340   using IsSizeStatic = vtkm::VecTraitsTagSizeStatic;
341 
342   VTKM_EXEC_CONT
343   static vtkm::IdComponent GetNumberOfComponents(const ScalarType&) { return 1; }
344 
345   VTKM_EXEC_CONT
346   static const ComponentType& GetComponent(const ScalarType& vector, vtkm::IdComponent)
347   {
348     return vector;
349   }
350   VTKM_EXEC_CONT
351   static ComponentType& GetComponent(ScalarType& vector, vtkm::IdComponent) { return vector; }
352 
353   VTKM_EXEC_CONT static void SetComponent(ScalarType& vector,
354                                           vtkm::IdComponent,
355                                           ComponentType value)
356   {
357     vector = value;
358   }
359 
360   template <vtkm::IdComponent destSize>
361   VTKM_EXEC_CONT static void CopyInto(const ScalarType& src, vtkm::Vec<ScalarType, destSize>& dest)
362   {
363     dest[0] = src;
364   }
365 };
366 } // namespace internal
367 
368 /// \brief VecTraits for Pair types
369 ///
370 /// Although a pair would seem better as a size-2 vector, we treat it as a
371 /// scalar. This is because a \c Vec is assumed to have the same type for
372 /// every component, and a pair in general has a different type for each
373 /// component. Thus we treat a pair as a "scalar" unit.
374 ///
375 template <typename T, typename U>
376 struct VecTraits<vtkm::Pair<T, U>> : public vtkm::internal::VecTraitsBasic<vtkm::Pair<T, U>>
377 {
378 };
379 
380 } // anonymous namespace
381 
382 #define VTKM_BASIC_TYPE_VECTOR(type)                                                               \
383   namespace vtkm                                                                                   \
384   {                                                                                                \
385   template <>                                                                                      \
386   struct VecTraits<type> : public vtkm::internal::VecTraitsBasic<type>                             \
387   {                                                                                                \
388   };                                                                                               \
389   }
390 
391 /// Allows you to treat basic types as if they were vectors.
392 
393 VTKM_BASIC_TYPE_VECTOR(float)
394 VTKM_BASIC_TYPE_VECTOR(double)
395 
396 VTKM_BASIC_TYPE_VECTOR(bool)
397 VTKM_BASIC_TYPE_VECTOR(char)
398 VTKM_BASIC_TYPE_VECTOR(signed char)
399 VTKM_BASIC_TYPE_VECTOR(unsigned char)
400 VTKM_BASIC_TYPE_VECTOR(short)
401 VTKM_BASIC_TYPE_VECTOR(unsigned short)
402 VTKM_BASIC_TYPE_VECTOR(int)
403 VTKM_BASIC_TYPE_VECTOR(unsigned int)
404 VTKM_BASIC_TYPE_VECTOR(long)
405 VTKM_BASIC_TYPE_VECTOR(unsigned long)
406 VTKM_BASIC_TYPE_VECTOR(long long)
407 VTKM_BASIC_TYPE_VECTOR(unsigned long long)
408 
409 //#undef VTKM_BASIC_TYPE_VECTOR
410 
411 #endif //vtk_m_VecTraits_h
412