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