vtk-m/vtkm/Types.h

1075 lines
28 KiB
C
Raw Normal View History

//============================================================================
// 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 <vtkm/internal/Configure.h>
#include <vtkm/internal/ExportMacros.h>
#include <vtkm/Assert.h>
#include <iostream>
2016-08-29 15:13:00 +00:00
#include <type_traits>
/*!
* \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::interop
* \brief Utility opengl interop functions
*
* vtkm::interop 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 <vtkm::IdComponent Size>
struct VecComponentWiseUnaryOperation
{
template<typename T, typename UnaryOpType>
VTKM_EXEC_CONT_EXPORT
T operator()(const T &v, const UnaryOpType &unaryOp) const
{
T result;
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
result[i] = unaryOp(v[i]);
}
return result;
}
};
template<>
struct VecComponentWiseUnaryOperation<1>
{
template<typename T, typename UnaryOpType>
VTKM_EXEC_CONT_EXPORT
T operator()(const T &v, const UnaryOpType &unaryOp) const
{
return T(unaryOp(v[0]));
}
};
template<>
struct VecComponentWiseUnaryOperation<2>
{
template<typename T, typename UnaryOpType>
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<typename T, typename UnaryOpType>
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<typename T, typename UnaryOpType>
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<typename T, typename BinaryOpType, typename ReturnT = T>
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<typename RightT>
VTKM_EXEC_CONT_EXPORT
ReturnT operator()(const RightT &rightValue) const
{
return static_cast<ReturnT>(this->BinaryOp(this->LeftValue,
static_cast<T>(rightValue)));
}
};
template<typename T, typename BinaryOpType, typename ReturnT = T>
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<typename LeftT>
VTKM_EXEC_CONT_EXPORT
ReturnT operator()(const LeftT &leftValue) const
{
return static_cast<ReturnT>(this->BinaryOp(static_cast<T>(leftValue),
this->RightValue));
}
};
} // 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<typename T>
VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b) const
{
return T(a + b);
}
};
struct Subtract
{
template<typename T>
VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b) const
{
return T(a - b);
}
};
struct Multiply
{
template<typename T>
VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b) const
{
return T(a * b);
}
};
struct Divide
{
template<typename T>
VTKM_EXEC_CONT_EXPORT T operator()(const T &a, const T &b) const
{
return T(a / b);
}
};
struct Negate
{
template<typename T>
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
//-----------------------------------------------------------------------------
// Pre declaration
template <typename T, vtkm::IdComponent Size>
class Vec;
namespace detail {
/// Base implementation of all Vec classes.
///
template <typename T, vtkm::IdComponent Size, typename DerivedClass>
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)
{
2016-10-23 13:11:38 +00:00
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
this->Components[i] = value;
}
}
template <typename OtherValueType, typename OtherDerivedType>
VTKM_EXEC_CONT_EXPORT VecBase(
const VecBase<OtherValueType, Size, OtherDerivedType>& src)
{
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
this->Components[i] = static_cast<T>(src[i]);
}
}
public:
VTKM_EXEC_CONT_EXPORT
vtkm::IdComponent GetNumberOfComponents() const
{
return NUM_COMPONENTS;
}
template <vtkm::IdComponent OtherSize>
VTKM_EXEC_CONT_EXPORT void CopyInto(
vtkm::Vec<ComponentType, OtherSize>& 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)
{
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
this->Components[i] = src[i];
}
return *static_cast<DerivedClass*>(this);
}
VTKM_EXEC_CONT_EXPORT
const ComponentType& operator[](vtkm::IdComponent idx) const
{
VTKM_ASSERT(idx >= 0);
VTKM_ASSERT(idx < this->NUM_COMPONENTS);
return this->Components[idx];
}
VTKM_EXEC_CONT_EXPORT
ComponentType& operator[](vtkm::IdComponent idx)
{
VTKM_ASSERT(idx >= 0);
VTKM_ASSERT(idx < this->NUM_COMPONENTS);
return this->Components[idx];
}
VTKM_EXEC_CONT_EXPORT
bool operator==(const DerivedClass& other) const
{
bool equal=true;
for(vtkm::IdComponent i=0; i < Size && equal; ++i)
{
equal = (this->Components[i] == other.Components[i]);
}
return equal;
}
VTKM_EXEC_CONT_EXPORT
bool operator<(const DerivedClass& other) const
{
for (vtkm::IdComponent i = 0; i < NUM_COMPONENTS; ++i)
{
// ignore equals as that represents check next value
if (this->Components[i] < other[i])
{
return true;
}
else if (other[i] < this->Components[i])
{
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 i = 1; i < Size; ++i)
{
result += this->Components[i] * other[i];
}
return result;
}
// 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
VTKM_EXEC_CONT_EXPORT
DerivedClass operator+(const DerivedClass& other) const
{
DerivedClass result;
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
result[i] = this->Components[i] + other[i];
}
return result;
}
VTKM_EXEC_CONT_EXPORT
DerivedClass& operator+=(const DerivedClass& other)
{
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
this->Components[i] += other[i];
}
return *static_cast<DerivedClass*>(this);
}
VTKM_EXEC_CONT_EXPORT
DerivedClass operator-(const DerivedClass& other) const
{
DerivedClass result;
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
result[i] = this->Components[i] - other[i];
}
return result;
}
VTKM_EXEC_CONT_EXPORT
DerivedClass& operator-=(const DerivedClass& other)
{
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
this->Components[i] -= other[i];
}
return *static_cast<DerivedClass*>(this);
}
VTKM_EXEC_CONT_EXPORT
DerivedClass operator*(const DerivedClass& other) const
{
DerivedClass result;
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
result[i] = this->Components[i] * other[i];
}
return result;
}
VTKM_EXEC_CONT_EXPORT
DerivedClass& operator*=(const DerivedClass& other)
{
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
this->Components[i] *= other[i];
}
return *static_cast<DerivedClass*>(this);
}
VTKM_EXEC_CONT_EXPORT
DerivedClass operator/(const DerivedClass& other) const
{
DerivedClass result;
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
result[i] = this->Components[i] / other[i];
}
return result;
}
VTKM_EXEC_CONT_EXPORT
DerivedClass& operator/=(const DerivedClass& other)
{
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
this->Components[i] /= other[i];
}
return *static_cast<DerivedClass*>(this);
}
#if (defined(VTKM_GCC) || defined(VTKM_CLANG))
#pragma GCC diagnostic pop
#endif // gcc || clang
VTKM_EXEC_CONT_EXPORT
ComponentType* GetPointer()
{
return this->Components;
}
VTKM_EXEC_CONT_EXPORT
const ComponentType* GetPointer() const
{
return this->Components;
}
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<typename T, vtkm::IdComponent Size>
class Vec : public detail::VecBase<T, Size, Vec<T,Size> >
{
typedef detail::VecBase<T, Size, Vec<T,Size> > 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<typename OtherType>
VTKM_EXEC_CONT_EXPORT
Vec(const Vec<OtherType, Size> &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<typename T>
class Vec<T, 0>
{
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<typename OtherType>
VTKM_EXEC_CONT_EXPORT Vec(const Vec<OtherType, NUM_COMPONENTS> &) { }
VTKM_EXEC_CONT_EXPORT
Vec<ComponentType, NUM_COMPONENTS> &
operator=(const Vec<ComponentType, NUM_COMPONENTS> &)
{
return *this;
}
VTKM_EXEC_CONT_EXPORT
ComponentType operator[](vtkm::IdComponent vtkmNotUsed(idx)) const
{
return ComponentType();
}
VTKM_EXEC_CONT_EXPORT
bool operator==(const Vec<T, NUM_COMPONENTS> &vtkmNotUsed(other)) const
{
return true;
}
VTKM_EXEC_CONT_EXPORT
bool operator!=(const Vec<T, NUM_COMPONENTS> &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<typename T>
class Vec<T,1> : public detail::VecBase<T, 1, Vec<T,1> >
{
typedef detail::VecBase<T, 1, Vec<T,1> > Superclass;
public:
VTKM_EXEC_CONT_EXPORT Vec() {}
VTKM_EXEC_CONT_EXPORT explicit Vec(const T& value) : Superclass(value) { }
template<typename OtherType>
VTKM_EXEC_CONT_EXPORT Vec(const Vec<OtherType, 1> &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<typename T>
class Vec<T,2> : public detail::VecBase<T, 2, Vec<T,2> >
{
typedef detail::VecBase<T, 2, Vec<T,2> > Superclass;
public:
VTKM_EXEC_CONT_EXPORT Vec() {}
VTKM_EXEC_CONT_EXPORT explicit Vec(const T& value) : Superclass(value) { }
template<typename OtherType>
VTKM_EXEC_CONT_EXPORT Vec(const Vec<OtherType, 2> &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<vtkm::Id,2> Id2;
template<typename T>
class Vec<T,3> : public detail::VecBase<T, 3, Vec<T,3> >
{
typedef detail::VecBase<T, 3, Vec<T,3> > Superclass;
public:
VTKM_EXEC_CONT_EXPORT Vec() {}
VTKM_EXEC_CONT_EXPORT explicit Vec(const T& value) : Superclass(value) { }
template<typename OtherType>
VTKM_EXEC_CONT_EXPORT Vec(const Vec<OtherType, 3> &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<vtkm::Id,3> Id3;
template<typename T>
class Vec<T,4> : public detail::VecBase<T, 4, Vec<T,4> >
{
typedef detail::VecBase<T, 4, Vec<T,4> > Superclass;
public:
VTKM_EXEC_CONT_EXPORT Vec() {}
VTKM_EXEC_CONT_EXPORT explicit Vec(const T& value) : Superclass(value) { }
template<typename OtherType>
VTKM_EXEC_CONT_EXPORT Vec(const Vec<OtherType, 4> &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;
}
};
/// Provides the appropriate type when not sure if using a Vec or a scalar in a
/// templated class or function. The \c Type in the struct is the same as the
/// \c ComponentType when \c NumComponents is 1 and a \c Vec otherwise.
///
template <typename ComponentType, vtkm::IdComponent NumComponents>
struct VecOrScalar
{
typedef vtkm::Vec<ComponentType, NumComponents> Type;
};
template <typename ComponentType>
struct VecOrScalar<ComponentType, 1>
{
typedef ComponentType Type;
};
/// Initializes and returns a Vec of length 2.
///
template<typename T>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<T,2> make_Vec(const T &x, const T &y)
{
return vtkm::Vec<T,2>(x, y);
}
/// Initializes and returns a Vec of length 3.
///
template<typename T>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<T,3> make_Vec(const T &x, const T &y, const T &z)
{
return vtkm::Vec<T,3>(x, y, z);
}
/// Initializes and returns a Vec of length 4.
///
template<typename T>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<T,4> make_Vec(const T &x, const T &y, const T &z, const T &w)
{
return vtkm::Vec<T,4>(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<typename U, typename V>
struct Pair;
template<typename T, vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT
T dot(const vtkm::Vec<T,Size> &a, const vtkm::Vec<T,Size> &b)
{
T result = T(a[0] * b[0]);
for (vtkm::IdComponent i = 1; i < Size; ++i)
{
result = T(result + a[i] * b[i]);
}
return result;
}
template<typename T>
VTKM_EXEC_CONT_EXPORT
T dot(const vtkm::Vec<T,2> &a, const vtkm::Vec<T,2> &b)
{
return T((a[0]*b[0]) + (a[1]*b[1]));
}
template<typename T>
VTKM_EXEC_CONT_EXPORT
T dot(const vtkm::Vec<T,3> &a, const vtkm::Vec<T,3> &b)
{
return T((a[0]*b[0]) + (a[1]*b[1]) + (a[2]*b[2]));
}
template <typename T>
VTKM_EXEC_CONT_EXPORT T
dot(const vtkm::Vec<T, 4>& a, const vtkm::Vec<T, 4>& b)
{
return T((a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]) + (a[3] * b[3]));
}
template <typename T, vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT T
ReduceSum(const vtkm::Vec<T, Size>& a)
{
T result = a[0];
for (vtkm::IdComponent i = 1; i < Size; ++i)
{
result += a[i];
}
return result;
}
template <typename T>
VTKM_EXEC_CONT_EXPORT T
ReduceSum(const vtkm::Vec<T, 2>& a)
{
return a[0] + a[1];
}
template <typename T>
VTKM_EXEC_CONT_EXPORT T
ReduceSum(const vtkm::Vec<T, 3>& a)
{
return a[0] + a[1] + a[2];
}
template <typename T>
VTKM_EXEC_CONT_EXPORT T
ReduceSum(const vtkm::Vec<T, 4>& a)
{
return a[0] + a[1] + a[2] + a[3];
}
template <typename T, vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT T
ReduceProduct(const vtkm::Vec<T, Size>& a)
{
T result = a[0];
for (vtkm::IdComponent i = 1; i < Size; ++i)
{
result *= a[i];
}
return result;
}
template <typename T>
VTKM_EXEC_CONT_EXPORT T
ReduceProduct(const vtkm::Vec<T, 2>& a)
{
return a[0] * a[1];
}
template <typename T>
VTKM_EXEC_CONT_EXPORT T
ReduceProduct(const vtkm::Vec<T, 3>& a)
{
return a[0] * a[1] * a[2];
}
template <typename T>
VTKM_EXEC_CONT_EXPORT T
ReduceProduct(const vtkm::Vec<T, 4>& a)
{
return a[0] * a[1] * a[2] * a[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<type>(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<typename T, vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<T, Size> operator*(T scalar, const vtkm::Vec<T, Size> &vec)
{
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
vec,
vtkm::internal::BindLeftBinaryOp<T,vtkm::Multiply>(scalar));
}
template<typename T, vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<T, Size> operator*(const vtkm::Vec<T, Size> &vec, T scalar)
{
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
vec,
vtkm::internal::BindRightBinaryOp<T,vtkm::Multiply>(scalar));
}
template<typename T, vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<T, Size>
operator*(vtkm::Float64 scalar, const vtkm::Vec<T, Size> &vec)
{
return vtkm::Vec<T, Size>(
vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
vec,
vtkm::internal::BindLeftBinaryOp<
vtkm::Float64,vtkm::Multiply,T>(scalar)));
}
template<typename T, vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<T, Size>
operator*(const vtkm::Vec<T, Size> &vec, vtkm::Float64 scalar)
{
return vtkm::Vec<T, Size>(
vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
vec,
vtkm::internal::BindRightBinaryOp<
vtkm::Float64,vtkm::Multiply,T>(scalar)));
}
template<vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<vtkm::Float64, Size>
operator*(vtkm::Float64 scalar, const vtkm::Vec<vtkm::Float64, Size> &vec)
{
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
vec,
vtkm::internal::BindLeftBinaryOp<
vtkm::Float64,vtkm::Multiply>(scalar));
}
template<vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<vtkm::Float64, Size>
operator*(const vtkm::Vec<vtkm::Float64, Size> &vec, vtkm::Float64 scalar)
{
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
vec,
vtkm::internal::BindRightBinaryOp<
vtkm::Float64,vtkm::Multiply>(scalar));
}
template<typename T, vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<T, Size> operator/(const vtkm::Vec<T, Size> &vec, T scalar)
{
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
vec,
vtkm::internal::BindRightBinaryOp<T,vtkm::Divide>(scalar));
}
template<typename T, vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<T, Size>
operator/(const vtkm::Vec<T, Size> &vec, vtkm::Float64 scalar)
{
return vtkm::Vec<T, Size>(
vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
vec,
vtkm::internal::BindRightBinaryOp<
vtkm::Float64,vtkm::Divide,T>(scalar)));
}
template<vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT
vtkm::Vec<vtkm::Float64, Size>
operator/(const vtkm::Vec<vtkm::Float64, Size> &vec, vtkm::Float64 scalar)
{
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
vec,
vtkm::internal::BindRightBinaryOp<
vtkm::Float64,vtkm::Divide>(scalar));
}
// The enable_if for this operator is effectively disabling the negate
// operator for Vec of unsigned integers. Another approach would be
2016-08-29 15:13:00 +00:00
// to use enable_if<!is_unsigned>. That would be more inclusive but would
// also allow other types like Vec<Vec<unsigned> >. If necessary, we could
// change this implementation to be more inclusive.
template<typename T, vtkm::IdComponent Size>
VTKM_EXEC_CONT_EXPORT
2016-08-29 15:13:00 +00:00
typename std::enable_if<
(std::is_floating_point<T>::value || std::is_signed<T>::value),
vtkm::Vec<T,Size>
>::type
operator-(const vtkm::Vec<T,Size> &x)
{
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
x, vtkm::Negate());
}
/// Helper function for printing out vectors during testing.
///
template<typename T, vtkm::IdComponent Size>
VTKM_CONT_EXPORT
std::ostream &operator<<(std::ostream &stream, const vtkm::Vec<T,Size> &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<typename T, typename U>
VTKM_EXEC_CONT_EXPORT
std::ostream &operator<<(std::ostream &stream, const vtkm::Pair<T,U> &vec)
{
return stream << "[" << vec.first << "," << vec.second << "]";
}
#endif //vtk_m_Types_h