//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ #ifndef vtk_m_Types_h #define vtk_m_Types_h #include #include #include #include #include #include #include /*! * \namespace vtkm * \brief VTK-m Toolkit. * * vtkm is the namespace for the VTK-m Toolkit. It contains other sub namespaces, * as well as basic data types and functions callable from all components in VTK-m * toolkit. * * \namespace vtkm::cont * \brief VTK-m Control Environment. * * vtkm::cont defines the publicly accessible API for the VTK-m Control * Environment. Users of the VTK-m Toolkit can use this namespace to access the * Control Environment. * * \namespace vtkm::cont::arg * \brief Transportation controls for Control Environment Objects. * * vtkm::cont::arg includes the classes that allows the vtkm::worklet::Dispatchers * to request Control Environment Objects to be transferred to the Execution Environment. * * \namespace vtkm::cont::cuda * \brief CUDA implementation for Control Environment. * * vtkm::cont::cuda includes the code to implement the VTK-m Control Environment * for the CUDA-based device adapter. * * \namespace vtkm::cont::openmp * \brief OPenMP implementation for Control Environment. * * vtkm::cont::openmp includes the code to implement the VTK-m Control Environment * for the OpenMP-based device adapter. * * \namespace vtkm::cont::serial * \brief Serial implementation for Control Environment. * * vtkm::cont::serial includes the code to implement the VTK-m Control Environment * for the serial device adapter. * * \namespace vtkm::cont::tbb * \brief TBB implementation for Control Environment. * * vtkm::cont::tbb includes the code to implement the VTK-m Control Environment * for the TBB-based device adapter. * * \namespace vtkm::exec * \brief VTK-m Execution Environment. * * vtkm::exec defines the publicly accessible API for the VTK-m Execution * Environment. Worklets typically use classes/apis defined within this * namespace alone. * * \namespace vtkm::exec::cuda * \brief CUDA implementation for Execution Environment. * * vtkm::exec::cuda includes the code to implement the VTK-m Execution Environment * for the CUDA-based device adapter. * * \namespace vtkm::exec::openmp * \brief CUDA implementation for Execution Environment. * * vtkm::exec::openmp includes the code to implement the VTK-m Execution Environment * for the OpenMP device adapter. * * \namespace vtkm::exec::serial * \brief CUDA implementation for Execution Environment. * * vtkm::exec::serial includes the code to implement the VTK-m Execution Environment * for the serial device adapter. * * \namespace vtkm::exec::tbb * \brief TBB implementation for Execution Environment. * * vtkm::exec::tbb includes the code to implement the VTK-m Execution Environment * for the TBB device adapter. * * \namespace vtkm::filter * \brief VTK-m Filters * * vtkm::filter is the collection of predefined filters that take data as input * and write new data as output. Filters operate on vtkm::cont::DataSet objects, * vtkm::cont::Fields, and other runtime typeless objects. * * \namespace vtkm::internal * \brief VTK-m Internal Environment * * vtkm::internal defines API which is internal and subject to frequent * change. This should not be used for projects using VTK-m. Instead it servers * are a reference for the developers of VTK-m. * * \namespace vtkm::interop * \brief VTK-m OpenGL Interoperability * * vtkm::interop defines the publicly accessible API for interoperability between * vtkm and OpenGL. * * \namespace vtkm::io * \brief VTK-m File input and output classes * * vtkm::io defines API for basic reading of VTK files. Intended to be used for * examples and testing. * * \namespace vtkm::rendering * \brief VTK-m Rendering * * vtkm::rendering defines API for * * \namespace vtkm::source * \brief VTK-m Input source such as Wavelet * * vtkm::source is the collection of predefined sources that generate data. * * \namespace vtkm::testing * \brief Internal testing classes * * \namespace vtkm::worklet * \brief VTK-m Worklets * * vtkm::worklet defines API for the low level worklets that operate on an element of data, * and the dispatcher that execute them in the execution environment. * * VTK-m provides numerous worklet implementations. These worklet implementations for the most * part provide the underlying implementations of the algorithms in vtkm::filter. * */ namespace vtkm { //***************************************************************************** // Typedefs for basic types. //***************************************************************************** /// Base type to use for 32-bit floating-point numbers. /// using Float32 = float; /// Base type to use for 64-bit floating-point numbers. /// using Float64 = double; /// Base type to use for 8-bit signed integer numbers. /// using Int8 = int8_t; /// Base type to use for 8-bit unsigned integer numbers. /// using UInt8 = uint8_t; /// Base type to use for 16-bit signed integer numbers. /// using Int16 = int16_t; /// Base type to use for 16-bit unsigned integer numbers. /// using UInt16 = uint16_t; /// Base type to use for 32-bit signed integer numbers. /// using Int32 = int32_t; /// Base type to use for 32-bit unsigned integer numbers. /// using UInt32 = uint32_t; /// \brief Base type to use to index small lists. /// /// This type represents a component ID (index of component in a vector). The number /// of components, being a value fixed at compile time, is generally assumed /// to be quite small. However, we are currently using a 32-bit width /// integer because modern processors tend to access them more efficiently /// than smaller widths. using IdComponent = vtkm::Int32; /// The default word size used for atomic bitwise operations. Universally /// supported on all devices. using WordTypeDefault = vtkm::UInt32; //In this order so that we exactly match the logic that exists in VTK #if (VTKM_SIZE_LONG_LONG == 8) || defined(VTKM_DOXYGEN_ONLY) /// Base type to use for 64-bit signed integer numbers. /// using Int64 = signed long long; /// Base type to use for 64-bit signed integer numbers. /// using UInt64 = unsigned long long; #define VTKM_UNUSED_INT_TYPE long #elif VTKM_SIZE_LONG == 8 /// Base type to use for 64-bit signed integer numbers. /// using Int64 = signed long; /// Base type to use for 64-bit unsigned integer numbers. /// using UInt64 = unsigned long; #define VTKM_UNUSED_INT_TYPE long long #else #error Could not find a 64-bit integer. #endif /// \brief Base type to use to index arrays. /// /// This type represents an ID (index into arrays). It should be used whenever /// indexing data that could grow arbitrarily large. /// #ifdef VTKM_USE_64BIT_IDS using Id = vtkm::Int64; #else using Id = vtkm::Int32; #endif /// The floating point type to use when no other precision is specified. #ifdef VTKM_USE_DOUBLE_PRECISION using FloatDefault = vtkm::Float64; #else using FloatDefault = vtkm::Float32; #endif namespace internal { /// Placeholder class for when a type is not applicable. struct NullType { }; } // namespace internal // Disable conversion warnings for Add, Subtract, Multiply, Divide on GCC only. // GCC creates false positive warnings for signed/unsigned char* operations. // This occurs because the values are implicitly casted up to int's for the // operation, and than casted back down to char's when return. // This causes a false positive warning, even when the values is within // the value types range #if (defined(VTKM_GCC) || defined(VTKM_CLANG)) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wconversion" #endif // gcc || clang struct Add { template inline VTKM_EXEC_CONT auto operator()(const T& a, const U& b) const -> decltype(a + b) { return a + b; } // If both arguments are short integers, explicitly cast the result back to the // type to avoid narrowing conversion warnings from operations that promote to // integers. template inline VTKM_EXEC_CONT typename std::enable_if::value && sizeof(T) < sizeof(int), T>::type operator()(T a, T b) const { return static_cast(a + b); } }; struct Subtract { template inline VTKM_EXEC_CONT auto operator()(const T& a, const U& b) const -> decltype(a - b) { return a - b; } // If both arguments are short integers, explicitly cast the result back to the // type to avoid narrowing conversion warnings from operations that promote to // integers. template inline VTKM_EXEC_CONT typename std::enable_if::value && sizeof(T) < sizeof(int), T>::type operator()(T a, T b) const { return static_cast(a - b); } }; struct Multiply { template inline VTKM_EXEC_CONT auto operator()(const T& a, const U& b) const -> decltype(a * b) { return a * b; } // If both arguments are short integers, explicitly cast the result back to the // type to avoid narrowing conversion warnings from operations that promote to // integers. template inline VTKM_EXEC_CONT typename std::enable_if::value && sizeof(T) < sizeof(int), T>::type operator()(T a, T b) const { return static_cast(a * b); } }; struct Divide { template inline VTKM_EXEC_CONT auto operator()(const T& a, const U& b) const -> decltype(a / b) { return a / b; } // If both arguments are short integers, explicitly cast the result back to the // type to avoid narrowing conversion warnings from operations that promote to // integers. template inline VTKM_EXEC_CONT typename std::enable_if::value && sizeof(T) < sizeof(int), T>::type operator()(T a, T b) const { return static_cast(a / b); } }; struct Negate { template inline VTKM_EXEC_CONT T operator()(const T& x) const { return T(-x); } }; #if (defined(VTKM_GCC) || defined(VTKM_CLANG)) #pragma GCC diagnostic pop #endif // gcc || clang //----------------------------------------------------------------------------- // Pre declaration template class VTKM_ALWAYS_EXPORT Vec; template class VTKM_ALWAYS_EXPORT VecC; template class VTKM_ALWAYS_EXPORT VecCConst; namespace detail { /// Base implementation of all Vec and VecC classes. /// // Disable conversion warnings for Add, Subtract, Multiply, Divide on GCC only. // GCC creates false positive warnings for signed/unsigned char* operations. // This occurs because the values are implicitly casted up to int's for the // operation, and than casted back down to char's when return. // This causes a false positive warning, even when the values is within // the value types range // // NVCC 7.5 and below does not recognize this pragma inside of class bodies, // so put them before entering the class. // #if (defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8)) #if (defined(VTKM_GCC) || defined(VTKM_CLANG)) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wfloat-conversion" #endif // gcc || clang #endif // use cuda < 8 template class VTKM_ALWAYS_EXPORT VecBaseCommon { public: using ComponentType = T; protected: VecBaseCommon() = default; VTKM_EXEC_CONT const DerivedClass& Derived() const { return *static_cast(this); } VTKM_EXEC_CONT DerivedClass& Derived() { return *static_cast(this); } private: // Only for internal use VTKM_EXEC_CONT inline vtkm::IdComponent NumComponents() const { return this->Derived().GetNumberOfComponents(); } // Only for internal use VTKM_EXEC_CONT inline const T& Component(vtkm::IdComponent index) const { return this->Derived()[index]; } // Only for internal use VTKM_EXEC_CONT inline T& Component(vtkm::IdComponent index) { return this->Derived()[index]; } public: template VTKM_EXEC_CONT void CopyInto(vtkm::Vec& dest) const { for (vtkm::IdComponent index = 0; (index < this->NumComponents()) && (index < OtherSize); index++) { dest[index] = this->Component(index); } } // Only works with Vec-like objects with operator[] and GetNumberOfComponents(). template VTKM_EXEC_CONT DerivedClass& operator=(const OtherVecType& src) { VTKM_ASSERT(this->NumComponents() == src.GetNumberOfComponents()); for (vtkm::IdComponent i = 0; i < this->NumComponents(); ++i) { this->Component(i) = src[i]; } return this->Derived(); } VTKM_EXEC_CONT bool operator==(const DerivedClass& other) const { bool equal = true; for (vtkm::IdComponent i = 0; i < this->NumComponents() && equal; ++i) { equal = (this->Component(i) == other[i]); } return equal; } VTKM_EXEC_CONT bool operator<(const DerivedClass& other) const { for (vtkm::IdComponent i = 0; i < this->NumComponents(); ++i) { // ignore equals as that represents check next value if (this->Component(i) < other[i]) { return true; } else if (other[i] < this->Component(i)) { return false; } } // if all same we are not less return false; } VTKM_EXEC_CONT bool operator!=(const DerivedClass& other) const { return !(this->operator==(other)); } #if (!(defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8))) #if (defined(VTKM_GCC) || defined(VTKM_CLANG)) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wfloat-conversion" #endif // gcc || clang #endif // not using cuda < 8 template inline VTKM_EXEC_CONT vtkm::Vec operator+( const vtkm::Vec& other) const { VTKM_ASSERT(Size == this->NumComponents()); vtkm::Vec result; for (vtkm::IdComponent i = 0; i < Size; ++i) { result[i] = this->Component(i) + other[i]; } return result; } template inline VTKM_EXEC_CONT DerivedClass& operator+=(const OtherClass& other) { VTKM_ASSERT(this->NumComponents() == other.GetNumberOfComponents()); for (vtkm::IdComponent i = 0; i < this->NumComponents(); ++i) { this->Component(i) += other[i]; } return this->Derived(); } template inline VTKM_EXEC_CONT vtkm::Vec operator-( const vtkm::Vec& other) const { VTKM_ASSERT(Size == this->NumComponents()); vtkm::Vec result; for (vtkm::IdComponent i = 0; i < Size; ++i) { result[i] = this->Component(i) - other[i]; } return result; } template inline VTKM_EXEC_CONT DerivedClass& operator-=(const OtherClass& other) { VTKM_ASSERT(this->NumComponents() == other.GetNumberOfComponents()); for (vtkm::IdComponent i = 0; i < this->NumComponents(); ++i) { this->Component(i) -= other[i]; } return this->Derived(); } template inline VTKM_EXEC_CONT vtkm::Vec operator*( const vtkm::Vec& other) const { vtkm::Vec result; for (vtkm::IdComponent i = 0; i < Size; ++i) { result[i] = this->Component(i) * other[i]; } return result; } template inline VTKM_EXEC_CONT DerivedClass& operator*=(const OtherClass& other) { VTKM_ASSERT(this->NumComponents() == other.GetNumberOfComponents()); for (vtkm::IdComponent i = 0; i < this->NumComponents(); ++i) { this->Component(i) *= other[i]; } return this->Derived(); } template inline VTKM_EXEC_CONT vtkm::Vec operator/( const vtkm::Vec& other) const { vtkm::Vec result; for (vtkm::IdComponent i = 0; i < Size; ++i) { result[i] = this->Component(i) / other[i]; } return result; } template VTKM_EXEC_CONT DerivedClass& operator/=(const OtherClass& other) { VTKM_ASSERT(this->NumComponents() == other.GetNumberOfComponents()); for (vtkm::IdComponent i = 0; i < this->NumComponents(); ++i) { this->Component(i) /= other[i]; } return this->Derived(); } #if (!(defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8))) #if (defined(VTKM_GCC) || defined(VTKM_CLANG)) #pragma GCC diagnostic pop #endif // gcc || clang #endif // not using cuda < 8 VTKM_EXEC_CONT ComponentType* GetPointer() { return &this->Component(0); } VTKM_EXEC_CONT const ComponentType* GetPointer() const { return &this->Component(0); } }; /// Base implementation of all Vec classes. /// template class VTKM_ALWAYS_EXPORT VecBase : public vtkm::detail::VecBaseCommon { public: using ComponentType = T; static constexpr vtkm::IdComponent NUM_COMPONENTS = Size; VecBase() = default; // The enable_if predicate will disable this constructor for Size=1 so that // the variadic constructor constexpr VecBase(T, Ts&&...) is called instead. VTKM_SUPPRESS_EXEC_WARNINGS template ::type = 0> VTKM_EXEC_CONT explicit VecBase(const ComponentType& value) { for (vtkm::IdComponent i = 0; i < Size; ++i) { this->Components[i] = value; } } VTKM_SUPPRESS_EXEC_WARNINGS template VTKM_EXEC_CONT constexpr VecBase(ComponentType value0, Ts&&... values) : Components{ value0, values... } { VTKM_STATIC_ASSERT(sizeof...(Ts) + 1 == Size); } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT VecBase(std::initializer_list values) { ComponentType* dest = this->Components; auto src = values.begin(); if (values.size() == 1) { for (vtkm::IdComponent i = 0; i < Size; ++i) { this->Components[i] = *src; ++dest; } } else { VTKM_ASSERT((values.size() == NUM_COMPONENTS) && "Vec object initialized wrong number of components."); for (; src != values.end(); ++src) { *dest = *src; ++dest; } } } #if (!(defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8))) #if (defined(VTKM_GCC) || defined(VTKM_CLANG)) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wfloat-conversion" #endif // gcc || clang #endif //not using cuda < 8 #if defined(VTKM_MSVC) #pragma warning(push) #pragma warning(disable : 4244) #endif VTKM_SUPPRESS_EXEC_WARNINGS template VTKM_EXEC_CONT explicit VecBase(const VecBase& src) { //DO NOT CHANGE THIS AND THE ABOVE PRAGMA'S UNLESS YOU FULLY UNDERSTAND THE //ISSUE https://gitlab.kitware.com/vtk/vtk-m/-/issues/221 for (vtkm::IdComponent i = 0; i < Size; ++i) { this->Components[i] = src[i]; } } public: inline VTKM_EXEC_CONT constexpr vtkm::IdComponent GetNumberOfComponents() const { return NUM_COMPONENTS; } inline VTKM_EXEC_CONT constexpr const ComponentType& operator[](vtkm::IdComponent idx) const { return this->Components[idx]; } inline VTKM_EXEC_CONT ComponentType& operator[](vtkm::IdComponent idx) { VTKM_ASSERT(idx >= 0); VTKM_ASSERT(idx < NUM_COMPONENTS); return this->Components[idx]; } VTKM_SUPPRESS_EXEC_WARNINGS template inline VTKM_EXEC_CONT DerivedClass operator+(const VecBaseCommon& other) const { const OtherClass& other_derived = static_cast(other); VTKM_ASSERT(NUM_COMPONENTS == other_derived.GetNumberOfComponents()); DerivedClass result; for (vtkm::IdComponent i = 0; i < NUM_COMPONENTS; ++i) { result[i] = this->Components[i] + static_cast(other_derived[i]); } return result; } VTKM_SUPPRESS_EXEC_WARNINGS template inline VTKM_EXEC_CONT DerivedClass operator-(const VecBaseCommon& other) const { const OtherClass& other_derived = static_cast(other); VTKM_ASSERT(NUM_COMPONENTS == other_derived.GetNumberOfComponents()); DerivedClass result; for (vtkm::IdComponent i = 0; i < NUM_COMPONENTS; ++i) { result[i] = this->Components[i] - static_cast(other_derived[i]); } return result; } VTKM_SUPPRESS_EXEC_WARNINGS template inline VTKM_EXEC_CONT DerivedClass operator*(const VecBaseCommon& other) const { const OtherClass& other_derived = static_cast(other); VTKM_ASSERT(NUM_COMPONENTS == other_derived.GetNumberOfComponents()); DerivedClass result; for (vtkm::IdComponent i = 0; i < NUM_COMPONENTS; ++i) { result[i] = this->Components[i] * static_cast(other_derived[i]); } return result; } VTKM_SUPPRESS_EXEC_WARNINGS template inline VTKM_EXEC_CONT DerivedClass operator/(const VecBaseCommon& other) const { const OtherClass& other_derived = static_cast(other); VTKM_ASSERT(NUM_COMPONENTS == other_derived.GetNumberOfComponents()); DerivedClass result; for (vtkm::IdComponent i = 0; i < NUM_COMPONENTS; ++i) { result[i] = this->Components[i] / static_cast(other_derived[i]); } return result; } #if (!(defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8))) #if (defined(VTKM_GCC) || defined(VTKM_CLANG)) #pragma GCC diagnostic pop #endif // gcc || clang #endif // not using cuda < 8 #if defined(VTKM_MSVC) #pragma warning(pop) #endif protected: ComponentType Components[NUM_COMPONENTS]; }; #if (defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8)) #if (defined(VTKM_GCC) || defined(VTKM_CLANG)) #pragma GCC diagnostic pop #endif // gcc || clang #endif // use cuda < 8 /// Base of all VecC and VecCConst classes. /// template class VTKM_ALWAYS_EXPORT VecCBase : public vtkm::detail::VecBaseCommon { protected: VTKM_EXEC_CONT VecCBase() {} }; } // namespace detail //----------------------------------------------------------------------------- /// \brief A short fixed-length array. /// /// The \c Vec templated class holds a short array of values of a size and /// type specified by the template arguments. /// /// The \c Vec class is most often used to represent vectors in the /// mathematical sense as a quantity with a magnitude and direction. Vectors /// are, of course, used extensively in computational geometry as well as /// physical simulations. The \c Vec class can be (and is) repurposed for more /// general usage of holding a fixed-length sequence of objects. /// /// There is no real limit to the size of the sequence (other than the largest /// number representable by vtkm::IdComponent), but the \c Vec class is really /// designed for small sequences (seldom more than 10). /// template class VTKM_ALWAYS_EXPORT Vec : public detail::VecBase> { using Superclass = detail::VecBase>; public: #ifdef VTKM_DOXYGEN_ONLY using ComponentType = T; static constexpr vtkm::IdComponent NUM_COMPONENTS = Size; #endif using Superclass::Superclass; Vec() = default; #if defined(_MSC_VER) && _MSC_VER < 1910 template constexpr Vec(T value, Ts&&... values) : Superclass(value, std::forward(values)...) { } #endif inline VTKM_EXEC_CONT void CopyInto(Vec& dest) const { dest = *this; } }; //----------------------------------------------------------------------------- // Specializations for common small tuples. We implement them a bit specially. // A vector of size 0 cannot use VecBase because it will try to create a // zero length array which troubles compilers. Vecs of size 0 are a bit // pointless but might occur in some generic functions or classes. template class VTKM_ALWAYS_EXPORT Vec { public: using ComponentType = T; static constexpr vtkm::IdComponent NUM_COMPONENTS = 0; Vec() = default; VTKM_EXEC_CONT explicit Vec(const ComponentType&) {} template VTKM_EXEC_CONT Vec(const Vec&) { } VTKM_EXEC_CONT Vec& operator=(const Vec&) { return *this; } inline VTKM_EXEC_CONT constexpr vtkm::IdComponent GetNumberOfComponents() const { return NUM_COMPONENTS; } VTKM_EXEC_CONT constexpr ComponentType operator[](vtkm::IdComponent vtkmNotUsed(idx)) const { return ComponentType(); } VTKM_EXEC_CONT bool operator==(const Vec& vtkmNotUsed(other)) const { return true; } VTKM_EXEC_CONT bool operator!=(const Vec& vtkmNotUsed(other)) const { return false; } }; // Vectors of size 1 should implicitly convert between the scalar and the // vector. Otherwise, it should behave the same. template class VTKM_ALWAYS_EXPORT Vec : public detail::VecBase> { using Superclass = detail::VecBase>; public: Vec() = default; VTKM_EXEC_CONT constexpr Vec(const T& value) : Superclass(value) { } template VTKM_EXEC_CONT Vec(const Vec& src) : Superclass(src) { } }; //----------------------------------------------------------------------------- // Specializations for common tuple sizes (with special names). template class VTKM_ALWAYS_EXPORT Vec : public detail::VecBase> { using Superclass = detail::VecBase>; public: Vec() = default; VTKM_EXEC_CONT Vec(const T& value) : Superclass(value) { } template VTKM_EXEC_CONT Vec(const Vec& src) : Superclass(src) { } VTKM_EXEC_CONT constexpr Vec(const T& x, const T& y) : Superclass(x, y) { } }; /// \brief Id2 corresponds to a 2-dimensional index. /// using Id2 = vtkm::Vec; /// \brief IdComponent2 corresponds to an index to a local (small) 2-d array or equivalent. /// using IdComponent2 = vtkm::Vec; /// \brief Vec2f corresponds to a 2-dimensional vector of floating point values. /// /// Each floating point value is of the default precision (i.e. vtkm::FloatDefault). It is /// typedef for vtkm::Vec. /// using Vec2f = vtkm::Vec; /// \brief Vec2f_32 corresponds to a 2-dimensional vector of 32-bit floating point values. /// /// It is typedef for vtkm::Vec. /// using Vec2f_32 = vtkm::Vec; /// \brief Vec2f_64 corresponds to a 2-dimensional vector of 64-bit floating point values. /// /// It is typedef for vtkm::Vec. /// using Vec2f_64 = vtkm::Vec; /// \brief Vec2i corresponds to a 2-dimensional vector of integer values. /// /// Each integer value is of the default precision (i.e. vtkm::Id). /// using Vec2i = vtkm::Vec; /// \brief Vec2i_8 corresponds to a 2-dimensional vector of 8-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec2i_8 = vtkm::Vec; /// \brief Vec2i_16 corresponds to a 2-dimensional vector of 16-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec2i_16 = vtkm::Vec; /// \brief Vec2i_32 corresponds to a 2-dimensional vector of 32-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec2i_32 = vtkm::Vec; /// \brief Vec2i_64 corresponds to a 2-dimensional vector of 64-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec2i_64 = vtkm::Vec; /// \brief Vec2ui corresponds to a 2-dimensional vector of unsigned integer values. /// /// Each integer value is of the default precision (following vtkm::Id). /// #ifdef VTKM_USE_64BIT_IDS using Vec2ui = vtkm::Vec; #else using Vec2ui = vtkm::Vec; #endif /// \brief Vec2ui_8 corresponds to a 2-dimensional vector of 8-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec2ui_8 = vtkm::Vec; /// \brief Vec2ui_16 corresponds to a 2-dimensional vector of 16-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec2ui_16 = vtkm::Vec; /// \brief Vec2ui_32 corresponds to a 2-dimensional vector of 32-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec2ui_32 = vtkm::Vec; /// \brief Vec2ui_64 corresponds to a 2-dimensional vector of 64-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec2ui_64 = vtkm::Vec; template class VTKM_ALWAYS_EXPORT Vec : public detail::VecBase> { using Superclass = detail::VecBase>; public: Vec() = default; VTKM_EXEC_CONT Vec(const T& value) : Superclass(value) { } template VTKM_EXEC_CONT Vec(const Vec& src) : Superclass(src) { } VTKM_EXEC_CONT constexpr Vec(const T& x, const T& y, const T& z) : Superclass(x, y, z) { } }; /// \brief Id3 corresponds to a 3-dimensional index for 3d arrays. /// /// Note that the precision of each index may be less than vtkm::Id. /// using Id3 = vtkm::Vec; /// \brief IdComponent2 corresponds to an index to a local (small) 3-d array or equivalent. /// using IdComponent3 = vtkm::Vec; /// \brief Vec3f corresponds to a 3-dimensional vector of floating point values. /// /// Each floating point value is of the default precision (i.e. vtkm::FloatDefault). It is /// typedef for vtkm::Vec. /// using Vec3f = vtkm::Vec; /// \brief Vec3f_32 corresponds to a 3-dimensional vector of 32-bit floating point values. /// /// It is typedef for vtkm::Vec. /// using Vec3f_32 = vtkm::Vec; /// \brief Vec3f_64 corresponds to a 3-dimensional vector of 64-bit floating point values. /// /// It is typedef for vtkm::Vec. /// using Vec3f_64 = vtkm::Vec; /// \brief Vec3i corresponds to a 3-dimensional vector of integer values. /// /// Each integer value is of the default precision (i.e. vtkm::Id). /// using Vec3i = vtkm::Vec; /// \brief Vec3i_8 corresponds to a 3-dimensional vector of 8-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec3i_8 = vtkm::Vec; /// \brief Vec3i_16 corresponds to a 3-dimensional vector of 16-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec3i_16 = vtkm::Vec; /// \brief Vec3i_32 corresponds to a 3-dimensional vector of 32-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec3i_32 = vtkm::Vec; /// \brief Vec3i_64 corresponds to a 3-dimensional vector of 64-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec3i_64 = vtkm::Vec; /// \brief Vec3ui corresponds to a 3-dimensional vector of unsigned integer values. /// /// Each integer value is of the default precision (following vtkm::Id). /// #ifdef VTKM_USE_64BIT_IDS using Vec3ui = vtkm::Vec; #else using Vec3ui = vtkm::Vec; #endif /// \brief Vec3ui_8 corresponds to a 3-dimensional vector of 8-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec3ui_8 = vtkm::Vec; /// \brief Vec3ui_16 corresponds to a 3-dimensional vector of 16-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec3ui_16 = vtkm::Vec; /// \brief Vec3ui_32 corresponds to a 3-dimensional vector of 32-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec3ui_32 = vtkm::Vec; /// \brief Vec3ui_64 corresponds to a 3-dimensional vector of 64-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec3ui_64 = vtkm::Vec; template class VTKM_ALWAYS_EXPORT Vec : public detail::VecBase> { using Superclass = detail::VecBase>; public: Vec() = default; VTKM_EXEC_CONT Vec(const T& value) : Superclass(value) { } template VTKM_EXEC_CONT Vec(const Vec& src) : Superclass(src) { } VTKM_EXEC_CONT constexpr Vec(const T& x, const T& y, const T& z, const T& w) : Superclass(x, y, z, w) { } }; /// \brief Id4 corresponds to a 4-dimensional index. /// using Id4 = vtkm::Vec; /// \brief IdComponent4 corresponds to an index to a local (small) 4-d array or equivalent. /// using IdComponent4 = vtkm::Vec; /// \brief Vec4f corresponds to a 4-dimensional vector of floating point values. /// /// Each floating point value is of the default precision (i.e. vtkm::FloatDefault). It is /// typedef for vtkm::Vec. /// using Vec4f = vtkm::Vec; /// \brief Vec4f_32 corresponds to a 4-dimensional vector of 32-bit floating point values. /// /// It is typedef for vtkm::Vec. /// using Vec4f_32 = vtkm::Vec; /// \brief Vec4f_64 corresponds to a 4-dimensional vector of 64-bit floating point values. /// /// It is typedef for vtkm::Vec. /// using Vec4f_64 = vtkm::Vec; /// \brief Vec4i corresponds to a 4-dimensional vector of integer values. /// /// Each integer value is of the default precision (i.e. vtkm::Id). /// using Vec4i = vtkm::Vec; /// \brief Vec4i_8 corresponds to a 4-dimensional vector of 8-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec4i_8 = vtkm::Vec; /// \brief Vec4i_16 corresponds to a 4-dimensional vector of 16-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec4i_16 = vtkm::Vec; /// \brief Vec4i_32 corresponds to a 4-dimensional vector of 32-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec4i_32 = vtkm::Vec; /// \brief Vec4i_64 corresponds to a 4-dimensional vector of 64-bit integer values. /// /// It is typedef for vtkm::Vec. /// using Vec4i_64 = vtkm::Vec; /// \brief Vec4ui corresponds to a 4-dimensional vector of unsigned integer values. /// /// Each integer value is of the default precision (following vtkm::Id). /// #ifdef VTKM_USE_64BIT_IDS using Vec4ui = vtkm::Vec; #else using Vec4ui = vtkm::Vec; #endif /// \brief Vec4ui_8 corresponds to a 4-dimensional vector of 8-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec4ui_8 = vtkm::Vec; /// \brief Vec4ui_16 corresponds to a 4-dimensional vector of 16-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec4ui_16 = vtkm::Vec; /// \brief Vec4ui_32 corresponds to a 4-dimensional vector of 32-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec4ui_32 = vtkm::Vec; /// \brief Vec4ui_64 corresponds to a 4-dimensional vector of 64-bit unsigned integer values. /// /// It is typedef for vtkm::Vec. /// using Vec4ui_64 = vtkm::Vec; /// Initializes and returns a Vec containing all the arguments. The arguments should all be the /// same type or compile issues will occur. /// template VTKM_EXEC_CONT constexpr vtkm::Vec make_Vec(T value0, Ts&&... args) { return vtkm::Vec(value0, T(args)...); } /// \brief A Vec-like representation for short arrays. /// /// The \c VecC class takes a short array of values and provides an interface /// that mimics \c Vec. This provides a mechanism to treat C arrays like a \c /// Vec. It is useful in situations where you want to use a \c Vec but the data /// must come from elsewhere or in certain situations where the size cannot be /// determined at compile time. In particular, \c Vec objects of different /// sizes can potentially all be converted to a \c VecC of the same type. /// /// Note that \c VecC holds a reference to an outside array given to it. If /// that array gets destroyed (for example because the source goes out of /// scope), the behavior becomes undefined. /// /// You cannot use \c VecC with a const type in its template argument. For /// example, you cannot declare VecC. If you want a /// non-mutable \c VecC, the \c VecCConst class (e.g. /// VecCConst). /// template class VTKM_ALWAYS_EXPORT VecC : public detail::VecCBase> { using Superclass = detail::VecCBase>; VTKM_STATIC_ASSERT_MSG(std::is_const::value == false, "You cannot use VecC with a const type as its template argument. " "Use either const VecC or VecCConst."); public: #ifdef VTKM_DOXYGEN_ONLY using ComponentType = T; #endif VTKM_EXEC_CONT VecC() : Components(nullptr) , NumberOfComponents(0) { } VTKM_EXEC_CONT VecC(T* array, vtkm::IdComponent size) : Components(array) , NumberOfComponents(size) { } template VTKM_EXEC_CONT VecC(vtkm::Vec& src) : Components(src.GetPointer()) , NumberOfComponents(Size) { } VTKM_EXEC_CONT explicit VecC(T& src) : Components(&src) , NumberOfComponents(1) { } VTKM_EXEC_CONT VecC(const VecC& src) : Components(src.Components) , NumberOfComponents(src.NumberOfComponents) { } inline VTKM_EXEC_CONT const T& operator[](vtkm::IdComponent index) const { VTKM_ASSERT(index >= 0); VTKM_ASSERT(index < this->NumberOfComponents); return this->Components[index]; } inline VTKM_EXEC_CONT T& operator[](vtkm::IdComponent index) { VTKM_ASSERT(index >= 0); VTKM_ASSERT(index < this->NumberOfComponents); return this->Components[index]; } inline VTKM_EXEC_CONT vtkm::IdComponent GetNumberOfComponents() const { return this->NumberOfComponents; } VTKM_EXEC_CONT VecC& operator=(const VecC& src) { VTKM_ASSERT(this->NumberOfComponents == src.GetNumberOfComponents()); for (vtkm::IdComponent index = 0; index < this->NumberOfComponents; index++) { (*this)[index] = src[index]; } return *this; } private: T* const Components; vtkm::IdComponent NumberOfComponents; }; /// \brief A const version of VecC /// /// \c VecCConst is a non-mutable form of \c VecC. It can be used in place of /// \c VecC when a constant array is available. /// /// A \c VecC can be automatically converted to a \c VecCConst, but not vice /// versa, so function arguments should use \c VecCConst when the data do not /// need to be changed. /// template class VTKM_ALWAYS_EXPORT VecCConst : public detail::VecCBase> { using Superclass = detail::VecCBase>; VTKM_STATIC_ASSERT_MSG(std::is_const::value == false, "You cannot use VecCConst with a const type as its template argument. " "Remove the const from the type."); public: #ifdef VTKM_DOXYGEN_ONLY using ComponentType = T; #endif VTKM_EXEC_CONT VecCConst() : Components(nullptr) , NumberOfComponents(0) { } VTKM_EXEC_CONT VecCConst(const T* array, vtkm::IdComponent size) : Components(array) , NumberOfComponents(size) { } template VTKM_EXEC_CONT VecCConst(const vtkm::Vec& src) : Components(src.GetPointer()) , NumberOfComponents(Size) { } VTKM_EXEC_CONT explicit VecCConst(const T& src) : Components(&src) , NumberOfComponents(1) { } VTKM_EXEC_CONT VecCConst(const VecCConst& src) : Components(src.Components) , NumberOfComponents(src.NumberOfComponents) { } VTKM_EXEC_CONT VecCConst(const VecC& src) : Components(src.Components) , NumberOfComponents(src.NumberOfComponents) { } inline VTKM_EXEC_CONT const T& operator[](vtkm::IdComponent index) const { VTKM_ASSERT(index >= 0); VTKM_ASSERT(index < this->NumberOfComponents); return this->Components[index]; } inline VTKM_EXEC_CONT vtkm::IdComponent GetNumberOfComponents() const { return this->NumberOfComponents; } private: const T* const Components; vtkm::IdComponent NumberOfComponents; // You are not allowed to assign to a VecCConst, so these operators are not // implemented and are disallowed. void operator=(const VecCConst&) = delete; void operator+=(const VecCConst&) = delete; void operator-=(const VecCConst&) = delete; void operator*=(const VecCConst&) = delete; void operator/=(const VecCConst&) = delete; }; /// Creates a \c VecC from an input array. /// template static inline VTKM_EXEC_CONT vtkm::VecC make_VecC(T* array, vtkm::IdComponent size) { return vtkm::VecC(array, size); } /// Creates a \c VecCConst from a constant input array. /// template static inline VTKM_EXEC_CONT vtkm::VecCConst make_VecC(const T* array, vtkm::IdComponent size) { return vtkm::VecCConst(array, size); } namespace detail { template static inline VTKM_EXEC_CONT auto vec_dot(const T& a, const T& b) { auto result = a[0] * b[0]; for (vtkm::IdComponent i = 1; i < a.GetNumberOfComponents(); ++i) { result = result + a[i] * b[i]; } return result; } template static inline VTKM_EXEC_CONT auto vec_dot(const vtkm::Vec& a, const vtkm::Vec& b) { auto result = a[0] * b[0]; for (vtkm::IdComponent i = 1; i < Size; ++i) { result = result + a[i] * b[i]; } return result; } } // namespace detail template static inline VTKM_EXEC_CONT auto Dot(const T& a, const T& b) { return detail::vec_dot(a, b); } template static inline VTKM_EXEC_CONT auto Dot(const vtkm::Vec& a, const vtkm::Vec& b) { return (a[0] * b[0]) + (a[1] * b[1]); } template static inline VTKM_EXEC_CONT auto Dot(const vtkm::Vec& a, const vtkm::Vec& b) { return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]); } template static inline VTKM_EXEC_CONT auto Dot(const vtkm::Vec& a, const vtkm::Vec& b) { return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]) + (a[3] * b[3]); } // Integer types of a width less than an integer get implicitly casted to // an integer when doing a multiplication. #define VTK_M_SCALAR_DOT(stype) \ static inline VTKM_EXEC_CONT auto dot(stype a, stype b) { return a * b; } /* LEGACY */ \ static inline VTKM_EXEC_CONT auto Dot(stype a, stype b) { return a * b; } VTK_M_SCALAR_DOT(vtkm::Int8) VTK_M_SCALAR_DOT(vtkm::UInt8) VTK_M_SCALAR_DOT(vtkm::Int16) VTK_M_SCALAR_DOT(vtkm::UInt16) VTK_M_SCALAR_DOT(vtkm::Int32) VTK_M_SCALAR_DOT(vtkm::UInt32) VTK_M_SCALAR_DOT(vtkm::Int64) VTK_M_SCALAR_DOT(vtkm::UInt64) VTK_M_SCALAR_DOT(vtkm::Float32) VTK_M_SCALAR_DOT(vtkm::Float64) // v============ LEGACY =============v template static inline VTKM_EXEC_CONT auto dot(const T& a, const T& b) -> decltype(detail::vec_dot(a, b)) { return vtkm::Dot(a, b); } template static inline VTKM_EXEC_CONT auto dot(const vtkm::Vec& a, const vtkm::Vec& b) { return vtkm::Dot(a, b); } template static inline VTKM_EXEC_CONT auto dot(const vtkm::Vec& a, const vtkm::Vec& b) { return vtkm::Dot(a, b); } template static inline VTKM_EXEC_CONT auto dot(const vtkm::Vec& a, const vtkm::Vec& b) { return vtkm::Dot(a, b); } // ^============ LEGACY =============^ template inline VTKM_EXEC_CONT T ReduceSum(const vtkm::Vec& a) { T result = a[0]; for (vtkm::IdComponent i = 1; i < Size; ++i) { result += a[i]; } return result; } template inline VTKM_EXEC_CONT T ReduceSum(const vtkm::Vec& a) { return a[0] + a[1]; } template inline VTKM_EXEC_CONT T ReduceSum(const vtkm::Vec& a) { return a[0] + a[1] + a[2]; } template inline VTKM_EXEC_CONT T ReduceSum(const vtkm::Vec& a) { return a[0] + a[1] + a[2] + a[3]; } template inline VTKM_EXEC_CONT T ReduceProduct(const vtkm::Vec& a) { T result = a[0]; for (vtkm::IdComponent i = 1; i < Size; ++i) { result *= a[i]; } return result; } template inline VTKM_EXEC_CONT T ReduceProduct(const vtkm::Vec& a) { return a[0] * a[1]; } template inline VTKM_EXEC_CONT T ReduceProduct(const vtkm::Vec& a) { return a[0] * a[1] * a[2]; } template inline VTKM_EXEC_CONT T ReduceProduct(const vtkm::Vec& a) { return a[0] * a[1] * a[2] * a[3]; } // A pre-declaration of vtkm::Pair so that classes templated on them can refer // to it. The actual implementation is in vtkm/Pair.h. template struct Pair; /// Helper function for printing out vectors during testing. /// template inline VTKM_CONT std::ostream& operator<<(std::ostream& stream, const vtkm::Vec& vec) { stream << "["; for (vtkm::IdComponent component = 0; component < Size - 1; component++) { stream << vec[component] << ","; } return stream << vec[Size - 1] << "]"; } /// Helper function for printing out pairs during testing. /// template inline VTKM_EXEC_CONT std::ostream& operator<<(std::ostream& stream, const vtkm::Pair& vec) { return stream << "[" << vec.first << "," << vec.second << "]"; } } // End of namespace vtkm #include // Declared inside of vtkm namespace so that the operator work with ADL lookup #endif //vtk_m_Types_h