//============================================================================ // 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. // // Copyright 2014 Sandia Corporation. // Copyright 2014 UT-Battelle, LLC. // Copyright 2014 Los Alamos National Security. // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // the U.S. Government retains certain rights in this software. // // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National // Laboratory (LANL), the U.S. Government retains certain rights in // this software. //============================================================================ #ifndef vtk_m_Types_h #define vtk_m_Types_h #include #include VTKM_THIRDPARTY_PRE_INCLUDE #include #include #include #include VTKM_THIRDPARTY_POST_INCLUDE #include /*! * \namespace vtkm * \brief VTKm Toolkit. * * vtkm is the namespace for the VTKm Toolkit. It contains other sub namespaces, * as well as basic data types and functions callable from all components in VTKm * toolkit. * * \namespace vtkm::cont * \brief VTKm Control Environment. * * vtkm::cont defines the publicly accessible API for the VTKm Control * Environment. Users of the VTKm Toolkit can use this namespace to access the * Control Environment. * * \namespace vtkm::cont::cuda * \brief CUDA implementation for Control Environment. * * vtkm::cont::cuda includes the code to implement the VTKm Control Environment * for CUDA-based platforms. * * \namespace vtkm::exec * \brief VTKm Execution Environment. * * vtkm::exec defines the publicly accessible API for the VTKm 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 VTKm Execution Environment * for CUDA-based platforms. * * \namespace vtkm::internal * \brief VTKm Internal Environment * * vtkm::internal defines API which is internal and subject to frequent * change. This should not be used for projects using VTKm. Instead it servers * are a reference for the developers of VTKm. * * \namespace vtkm::opengl * \brief Utility opengl interop functions * * vtkm::opengl defines the publicly accessible API for interoperability between * vtkm and opengl. * * \namespace vtkm::testing * \brief Internal testing classes * */ namespace vtkm { //***************************************************************************** // Typedefs for basic types. //***************************************************************************** /// Alignment requirements are prescribed by CUDA on device (Table B-1 in NVIDIA /// CUDA C Programming Guide 4.0) #if VTKM_SIZE_FLOAT == 4 typedef float Float32; #else #error Could not find a 32-bit float. #endif #if VTKM_SIZE_DOUBLE == 8 typedef double Float64; #else #error Could not find a 64-bit float. #endif #if VTKM_SIZE_CHAR == 1 typedef signed char Int8; typedef unsigned char UInt8; #else #error Could not find an 8-bit integer. #endif #if VTKM_SIZE_SHORT == 2 typedef signed short Int16; typedef unsigned short UInt16; #else #error Could not find a 16-bit integer. #endif #if VTKM_SIZE_INT == 4 typedef signed int Int32; typedef unsigned int UInt32; #else #error Could not find a 32-bit integer. #endif //In this order so that we exactly match the logic that exists in VTK #if VTKM_SIZE_LONG_LONG == 8 typedef signed long long Int64; typedef unsigned long long UInt64; #elif VTKM_SIZE_LONG == 8 typedef signed long Int64; typedef unsigned long UInt64; #else #error Could not find a 64-bit integer. #endif //----------------------------------------------------------------------------- #if VTKM_SIZE_ID == 4 /// Represents an ID (index into arrays). typedef vtkm::Int32 Id; #elif VTKM_SIZE_ID == 8 /// Represents an ID. typedef vtkm::Int64 Id; #else #error Unknown Id Size #endif /// 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. typedef vtkm::Int32 IdComponent; #ifdef VTKM_USE_DOUBLE_PRECISION /// The floating point type to use when no other precision is specified. typedef vtkm::Float64 FloatDefault; #else //VTKM_USE_DOUBLE_PRECISION /// The floating point type to use when no other precision is specified. typedef vtkm::Float32 FloatDefault; #endif //VTKM_USE_DOUBLE_PRECISION namespace internal { //----------------------------------------------------------------------------- /// Placeholder class for when a type is not applicable. /// struct NullType { }; //----------------------------------------------------------------------------- template struct VecEquals { template VTKM_EXEC_CONT_EXPORT bool operator()(const T& a, const T& b) const { bool equal = true; for (vtkm::IdComponent componentIndex = 0; equal && (componentIndex < Size); componentIndex++) { equal &= a[componentIndex] == b[componentIndex]; } return equal; } }; template<> struct VecEquals<1> { template VTKM_EXEC_CONT_EXPORT bool operator()(const T& a, const T& b) const { return a[0] == b[0]; } }; template<> struct VecEquals<2> { template VTKM_EXEC_CONT_EXPORT bool operator()(const T& a, const T& b) const { return ((a[0] == b[0]) && (a[1] == b[1])); } }; template<> struct VecEquals<3> { template VTKM_EXEC_CONT_EXPORT bool operator()(const T& a, const T& b) const { return ((a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2])); } }; template<> struct VecEquals<4> { template VTKM_EXEC_CONT_EXPORT bool operator()(const T& a, const T& b) const { return ((a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3])); } }; template struct AssignScalarToVec { template VTKM_EXEC_CONT_EXPORT void operator()(VectorType &dest, const ComponentType &src) { for (vtkm::IdComponent componentIndex = 0; componentIndex < Size; componentIndex++) { dest[componentIndex] = src; } } }; template<> struct AssignScalarToVec<1> { template VTKM_EXEC_CONT_EXPORT void operator()(VectorType &dest, const ComponentType &src) { dest[0] = src; } }; template<> struct AssignScalarToVec<2> { template VTKM_EXEC_CONT_EXPORT void operator()(VectorType &dest, const ComponentType &src) { dest[0] = src; dest[1] = src; } }; template<> struct AssignScalarToVec<3> { template VTKM_EXEC_CONT_EXPORT void operator()(VectorType &dest, const ComponentType &src) { dest[0] = src; dest[1] = src; dest[2] = src; } }; template<> struct AssignScalarToVec<4> { template VTKM_EXEC_CONT_EXPORT void operator()(VectorType &dest, const ComponentType &src) { dest[0] = src; dest[1] = src; dest[2] = src; dest[3] = src; } }; template struct VecCopy { template VTKM_EXEC_CONT_EXPORT void operator()(T1 &dest, const T2 &src) { for (vtkm::IdComponent componentIndex = 0; componentIndex < Size; componentIndex++) { dest[componentIndex] = CType(src[componentIndex]); } } }; template struct VecCopy { template VTKM_EXEC_CONT_EXPORT void operator()(T1 &dest, const T2 &src) { dest[0] = CType(src[0]); } }; template struct VecCopy { template VTKM_EXEC_CONT_EXPORT void operator()(T1 &dest, const T2 &src) { dest[0] = CType(src[0]); dest[1] = CType(src[1]); } }; template struct VecCopy { template VTKM_EXEC_CONT_EXPORT void operator()(T1 &dest, const T2 &src) { dest[0] = CType(src[0]); dest[1] = CType(src[1]); dest[2] = CType(src[2]); } }; template struct VecCopy { template VTKM_EXEC_CONT_EXPORT void operator()(T1 &dest, const T2 &src) { dest[0] = CType(src[0]); dest[1] = CType(src[1]); dest[2] = CType(src[2]); dest[3] = CType(src[3]); } }; template struct VecSum { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &x) { typename T::ComponentType sum = x[0]; for (vtkm::IdComponent componentIndex = 1; componentIndex < Size; componentIndex++) { sum += x[componentIndex]; } return sum; } }; template<> struct VecSum<0> { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &) { return T::ComponentType(0); } }; template<> struct VecSum<1> { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &x) { return x[0]; } }; template<> struct VecSum<2> { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &x) { return x[0] + x[1]; } }; template<> struct VecSum<3> { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &x) { return x[0] + x[1] + x[2]; } }; template<> struct VecSum<4> { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &x) { return x[0] + x[1] + x[2] + x[3]; } }; template struct VecProduct { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &x) { typename T::ComponentType product = x[0]; for (vtkm::IdComponent componentIndex = 1; componentIndex < Size; componentIndex++) { product *= x[componentIndex]; } return product; } }; template<> struct VecProduct<0> { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &) { return T::ComponentType(1); } }; template<> struct VecProduct<1> { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &x) { return x[0]; } }; template<> struct VecProduct<2> { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &x) { return x[0] * x[1]; } }; template<> struct VecProduct<3> { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &x) { return x[0] * x[1] * x[2]; } }; template<> struct VecProduct<4> { template VTKM_EXEC_CONT_EXPORT typename T::ComponentType operator()(const T &x) { return x[0] * x[1] * x[2] * x[3]; } }; template struct VecComponentWiseBinaryOperation { template VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b, const BinaryOpType &binaryOp) const { T result; for (vtkm::IdComponent componentIndex = 0; componentIndex < Size; componentIndex++) { result[componentIndex] = binaryOp(a[componentIndex], b[componentIndex]); } return result; } }; template<> struct VecComponentWiseBinaryOperation<1> { template VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b, const BinaryOpType &binaryOp) const { return T(binaryOp(a[0], b[0])); } }; template<> struct VecComponentWiseBinaryOperation<2> { template VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b, const BinaryOpType &binaryOp) const { return T(binaryOp(a[0], b[0]), binaryOp(a[1], b[1])); } }; template<> struct VecComponentWiseBinaryOperation<3> { template VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b, const BinaryOpType &binaryOp) const { return T(binaryOp(a[0], b[0]), binaryOp(a[1], b[1]), binaryOp(a[2], b[2])); } }; template<> struct VecComponentWiseBinaryOperation<4> { template VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b, const BinaryOpType &binaryOp) const { return T(binaryOp(a[0], b[0]), binaryOp(a[1], b[1]), binaryOp(a[2], b[2]), binaryOp(a[3], b[3])); } }; template struct VecComponentWiseUnaryOperation { template VTKM_EXEC_CONT_EXPORT T operator()(const T &v, const UnaryOpType &unaryOp) const { T result; for (vtkm::IdComponent componentIndex = 0; componentIndex < Size; componentIndex++) { result[componentIndex] = unaryOp(v[componentIndex]); } return result; } }; template<> struct VecComponentWiseUnaryOperation<1> { template VTKM_EXEC_CONT_EXPORT T operator()(const T &v, const UnaryOpType &unaryOp) const { return T(unaryOp(v[0])); } }; template<> struct VecComponentWiseUnaryOperation<2> { template VTKM_EXEC_CONT_EXPORT T operator()(const T &v, const UnaryOpType &unaryOp) const { return T(unaryOp(v[0]), unaryOp(v[1])); } }; template<> struct VecComponentWiseUnaryOperation<3> { template VTKM_EXEC_CONT_EXPORT T operator()(const T &v, const UnaryOpType &unaryOp) const { return T(unaryOp(v[0]), unaryOp(v[1]), unaryOp(v[2])); } }; template<> struct VecComponentWiseUnaryOperation<4> { template VTKM_EXEC_CONT_EXPORT T operator()(const T &v, const UnaryOpType &unaryOp) const { return T(unaryOp(v[0]), unaryOp(v[1]), unaryOp(v[2]), unaryOp(v[3])); } }; template struct BindLeftBinaryOp { // Warning: a reference. const T &LeftValue; const BinaryOpType BinaryOp; VTKM_EXEC_CONT_EXPORT BindLeftBinaryOp(const T &leftValue, BinaryOpType binaryOp = BinaryOpType()) : LeftValue(leftValue), BinaryOp(binaryOp) { } template VTKM_EXEC_CONT_EXPORT ReturnT operator()(const RightT &rightValue) const { return static_cast(this->BinaryOp(this->LeftValue, static_cast(rightValue))); } }; template struct BindRightBinaryOp { // Warning: a reference. const T &RightValue; const BinaryOpType BinaryOp; VTKM_EXEC_CONT_EXPORT BindRightBinaryOp(const T &rightValue, BinaryOpType binaryOp = BinaryOpType()) : RightValue(rightValue), BinaryOp(binaryOp) { } template VTKM_EXEC_CONT_EXPORT ReturnT operator()(const LeftT &leftValue) const { return static_cast(this->BinaryOp(static_cast(leftValue), this->RightValue)); } }; // 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 VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b) const { return T(a + b); } }; struct Subtract { template VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b) const { return T(a - b); } }; struct Multiply { template VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b) const { return T(a * b); } }; struct Divide { template VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b) const { return T(a / b); } }; struct Negate { template VTKM_EXEC_CONT_EXPORT T operator()(const T &x) const { return T(-x); } }; #if (defined(VTKM_GCC) || defined(VTKM_CLANG)) #pragma GCC diagnostic pop #endif // gcc || clang } // namespace internal //----------------------------------------------------------------------------- // Pre declaration template class Vec; namespace detail { /// Base implementation of all Vec classes. /// template class VecBase { public: typedef T ComponentType; static const vtkm::IdComponent NUM_COMPONENTS=Size; protected: VTKM_EXEC_CONT_EXPORT VecBase() {} VTKM_EXEC_CONT_EXPORT explicit VecBase(const ComponentType& value) { vtkm::internal::AssignScalarToVec()( this->Components, value); } template VTKM_EXEC_CONT_EXPORT VecBase(const VecBase &src) { vtkm::internal::VecCopy()( this->Components, src); } public: VTKM_EXEC_CONT_EXPORT vtkm::IdComponent GetNumberOfComponents() const { return NUM_COMPONENTS; } template VTKM_EXEC_CONT_EXPORT void CopyInto(vtkm::Vec &dest) const { for (vtkm::IdComponent index = 0; (index < NUM_COMPONENTS) && (index < OtherSize); index++) { dest[index] = (*this)[index]; } } VTKM_EXEC_CONT_EXPORT DerivedClass &operator=(const DerivedClass &src) { vtkm::internal::VecCopy()( this->Components, src); return *reinterpret_cast(this); } VTKM_EXEC_CONT_EXPORT const ComponentType &operator[](vtkm::IdComponent idx) const { return this->Components[idx]; } VTKM_EXEC_CONT_EXPORT ComponentType &operator[](vtkm::IdComponent idx) { return this->Components[idx]; } VTKM_EXEC_CONT_EXPORT bool operator==(const DerivedClass &other) const { return vtkm::internal::VecEquals()( *reinterpret_cast(this), other); } VTKM_EXEC_CONT_EXPORT bool operator<(const DerivedClass &other) const { for(vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) { //ignore equals as that represents check next value if(this->Components[componentIndex] < other[componentIndex]) { return true; } else if(other[componentIndex] < this->Components[componentIndex]) { return false; } } //if all same we are not less return false; } VTKM_EXEC_CONT_EXPORT bool operator!=(const DerivedClass &other) const { return !(this->operator==(other)); } VTKM_EXEC_CONT_EXPORT ComponentType Dot(const DerivedClass &other) const { ComponentType result = this->Components[0]*other[0]; for (vtkm::IdComponent componentIndex = 1; componentIndex < Size; componentIndex++) { result += this->Components[componentIndex]*other[componentIndex]; } return result; } VTKM_EXEC_CONT_EXPORT DerivedClass operator+(const DerivedClass &other) const { return vtkm::internal::VecComponentWiseBinaryOperation()( *reinterpret_cast(this), other, vtkm::internal::Add()); } VTKM_EXEC_CONT_EXPORT DerivedClass operator-(const DerivedClass &other) const { return vtkm::internal::VecComponentWiseBinaryOperation()( *reinterpret_cast(this), other, vtkm::internal::Subtract()); } VTKM_EXEC_CONT_EXPORT DerivedClass operator*(const DerivedClass &other) const { return vtkm::internal::VecComponentWiseBinaryOperation()( *reinterpret_cast(this), other, vtkm::internal::Multiply()); } VTKM_EXEC_CONT_EXPORT DerivedClass operator/(const DerivedClass &other) const { return vtkm::internal::VecComponentWiseBinaryOperation()( *reinterpret_cast(this), other, vtkm::internal::Divide()); } protected: ComponentType Components[NUM_COMPONENTS]; }; } // 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 /// phyiscal 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 Vec : public detail::VecBase > { typedef detail::VecBase > Superclass; public: #ifdef VTKM_DOXYGEN_ONLY typedef T ComponentType; static const vtkm::IdComponent NUM_COMPONENTS=Size; #endif VTKM_EXEC_CONT_EXPORT Vec() {} VTKM_EXEC_CONT_EXPORT explicit Vec(const T& value) : Superclass(value) { } // VTKM_EXEC_CONT_EXPORT explicit Vec(const T* values) : Superclass(values) { } template VTKM_EXEC_CONT_EXPORT Vec(const Vec &src) : Superclass(src) { } }; //----------------------------------------------------------------------------- // 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 Vec { public: typedef T ComponentType; static const vtkm::IdComponent NUM_COMPONENTS = 0; VTKM_EXEC_CONT_EXPORT Vec() {} VTKM_EXEC_CONT_EXPORT explicit Vec(const ComponentType&) { } template VTKM_EXEC_CONT_EXPORT Vec(const Vec &) { } VTKM_EXEC_CONT_EXPORT Vec & operator=(const Vec &) { return *this; } VTKM_EXEC_CONT_EXPORT ComponentType operator[](vtkm::IdComponent vtkmNotUsed(idx)) const { return ComponentType(); } VTKM_EXEC_CONT_EXPORT bool operator==(const Vec &vtkmNotUsed(other)) const { return true; } VTKM_EXEC_CONT_EXPORT 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 Vec : public detail::VecBase > { typedef detail::VecBase > Superclass; public: VTKM_EXEC_CONT_EXPORT Vec() {} VTKM_EXEC_CONT_EXPORT explicit Vec(const T& value) : Superclass(value) { } template VTKM_EXEC_CONT_EXPORT Vec(const Vec &src) : Superclass(src) { } // This convenience operator removed because it was causing ambiguous // overload errors // VTKM_EXEC_CONT_EXPORT // operator T() const // { // return this->Components[0]; // } }; //----------------------------------------------------------------------------- // Specializations for common tuple sizes (with special names). template class Vec : public detail::VecBase > { typedef detail::VecBase > Superclass; public: VTKM_EXEC_CONT_EXPORT Vec() {} VTKM_EXEC_CONT_EXPORT explicit Vec(const T& value) : Superclass(value) { } template VTKM_EXEC_CONT_EXPORT Vec(const Vec &src) : Superclass(src) { } VTKM_EXEC_CONT_EXPORT Vec(const T &x, const T &y) { this->Components[0] = x; this->Components[1] = y; } }; /// Id2 corresponds to a 2-dimensional index typedef vtkm::Vec Id2; template class Vec : public detail::VecBase > { typedef detail::VecBase > Superclass; public: VTKM_EXEC_CONT_EXPORT Vec() {} VTKM_EXEC_CONT_EXPORT explicit Vec(const T& value) : Superclass(value) { } template VTKM_EXEC_CONT_EXPORT Vec(const Vec &src) : Superclass(src) { } VTKM_EXEC_CONT_EXPORT Vec(const T &x, const T &y, const T &z) { this->Components[0] = x; this->Components[1] = y; this->Components[2] = z; } }; /// Id3 corresponds to a 3-dimensional index for 3d arrays. Note that /// the precision of each index may be less than vtkm::Id. typedef vtkm::Vec Id3; template class Vec : public detail::VecBase > { typedef detail::VecBase > Superclass; public: VTKM_EXEC_CONT_EXPORT Vec() {} VTKM_EXEC_CONT_EXPORT explicit Vec(const T& value) : Superclass(value) { } template VTKM_EXEC_CONT_EXPORT Vec(const Vec &src) : Superclass(src) { } VTKM_EXEC_CONT_EXPORT Vec(const T &x, const T &y, const T &z, const T &w) { this->Components[0] = x; this->Components[1] = y; this->Components[2] = z; this->Components[3] = w; } }; /// Initializes and returns a Vec of length 2. /// template VTKM_EXEC_CONT_EXPORT vtkm::Vec make_Vec(const T &x, const T &y) { return vtkm::Vec(x, y); } /// Initializes and returns a Vec of length 3. /// template VTKM_EXEC_CONT_EXPORT vtkm::Vec make_Vec(const T &x, const T &y, const T &z) { return vtkm::Vec(x, y, z); } /// Initializes and returns a Vec of length 4. /// template VTKM_EXEC_CONT_EXPORT vtkm::Vec make_Vec(const T &x, const T &y, const T &z, const T &w) { return vtkm::Vec(x, y, z, w); } // 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; template VTKM_EXEC_CONT_EXPORT T dot(const vtkm::Vec &a, const vtkm::Vec &b) { T result = T(a[0]*b[0]); for (vtkm::IdComponent componentIndex = 1; componentIndex < Size; componentIndex++) { result = T(result + a[componentIndex]*b[componentIndex]); } return result; } template VTKM_EXEC_CONT_EXPORT T dot(const vtkm::Vec &a, const vtkm::Vec &b) { return T((a[0]*b[0]) + (a[1]*b[1])); } template VTKM_EXEC_CONT_EXPORT T dot(const vtkm::Vec &a, const vtkm::Vec &b) { return T((a[0]*b[0]) + (a[1]*b[1]) + (a[2]*b[2])); } template VTKM_EXEC_CONT_EXPORT T dot(const vtkm::Vec &a, const vtkm::Vec &b) { return T((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_INTEGER_PROMOTION_SCALAR_DOT(type) \ VTKM_EXEC_CONT_EXPORT type dot(type a, type b) { return static_cast(a * b); } VTK_M_INTEGER_PROMOTION_SCALAR_DOT(vtkm::Int8) VTK_M_INTEGER_PROMOTION_SCALAR_DOT(vtkm::UInt8) VTK_M_INTEGER_PROMOTION_SCALAR_DOT(vtkm::Int16) VTK_M_INTEGER_PROMOTION_SCALAR_DOT(vtkm::UInt16) #define VTK_M_SCALAR_DOT(type) \ VTKM_EXEC_CONT_EXPORT type dot(type a, type b) { return a * b; } 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) } // End of namespace vtkm // Declared outside of vtkm namespace so that the operator works with all code. template VTKM_EXEC_CONT_EXPORT vtkm::Vec operator*(T scalar, const vtkm::Vec &vec) { return vtkm::internal::VecComponentWiseUnaryOperation()( vec, vtkm::internal::BindLeftBinaryOp(scalar)); } template VTKM_EXEC_CONT_EXPORT vtkm::Vec operator*(const vtkm::Vec &vec, T scalar) { return vtkm::internal::VecComponentWiseUnaryOperation()( vec, vtkm::internal::BindRightBinaryOp(scalar)); } template VTKM_EXEC_CONT_EXPORT vtkm::Vec operator*(vtkm::Float64 scalar, const vtkm::Vec &vec) { return vtkm::Vec( vtkm::internal::VecComponentWiseUnaryOperation()( vec, vtkm::internal::BindLeftBinaryOp< vtkm::Float64,vtkm::internal::Multiply,T>(scalar))); } template VTKM_EXEC_CONT_EXPORT vtkm::Vec operator*(const vtkm::Vec &vec, vtkm::Float64 scalar) { return vtkm::Vec( vtkm::internal::VecComponentWiseUnaryOperation()( vec, vtkm::internal::BindRightBinaryOp< vtkm::Float64,vtkm::internal::Multiply,T>(scalar))); } template VTKM_EXEC_CONT_EXPORT vtkm::Vec operator*(vtkm::Float64 scalar, const vtkm::Vec &vec) { return vtkm::internal::VecComponentWiseUnaryOperation()( vec, vtkm::internal::BindLeftBinaryOp< vtkm::Float64,vtkm::internal::Multiply>(scalar)); } template VTKM_EXEC_CONT_EXPORT vtkm::Vec operator*(const vtkm::Vec &vec, vtkm::Float64 scalar) { return vtkm::internal::VecComponentWiseUnaryOperation()( vec, vtkm::internal::BindRightBinaryOp< vtkm::Float64,vtkm::internal::Multiply>(scalar)); } // The enable_if for this operator is effectively disabling the negate // operator for Vec of unsigned integers. Another approach would be // to use disable_if. That would be more inclusive but would // also allow other types like Vec >. If necessary, we could // change this implementation to be more inclusive. template VTKM_EXEC_CONT_EXPORT typename boost::enable_if< typename boost::mpl::or_< typename boost::is_floating_point::type, typename boost::is_signed::type>::type, vtkm::Vec >::type operator-(const vtkm::Vec &x) { return vtkm::internal::VecComponentWiseUnaryOperation()( x, vtkm::internal::Negate()); } /// Helper function for printing out vectors during testing. /// template VTKM_CONT_EXPORT 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 VTKM_EXEC_CONT_EXPORT std::ostream &operator<<(std::ostream &stream, const vtkm::Pair &vec) { return stream << "[" << vec.first << "," << vec.second << "]"; } #endif //vtk_m_Types_h