vtk-m/vtkm/Types.h
Kenneth Moreland b80b7e2e71 Add VTK-m User's Guide to source
This is a start of moving the VTK-m User's Guide into the VTK-m source.
This is only the start of the process. There are several goals of this
work.

1. Integrate the documentation into the source code better to better
   keep the code up to date.
2. Move the documentation over to Sphinx so that it can be posted online
   and be more easily linked.
3. Incoporate Doxygen into the guide to keep the documentation
   consistent.
4. Build the user guide examples as part of the VTK-m CI to catch
   compatibility changes quickly.
2023-10-17 11:31:27 -04:00

1640 lines
47 KiB
C++

//============================================================================
// 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 <vtkm/internal/Configure.h>
#include <vtkm/internal/ExportMacros.h>
#include <vtkm/Assert.h>
#include <vtkm/StaticAssert.h>
#include <cstdint>
#include <iostream>
#include <type_traits>
/*!
* \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 <typename T, typename U>
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 <typename T>
inline VTKM_EXEC_CONT
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
operator()(T a, T b) const
{
return static_cast<T>(a + b);
}
};
struct Subtract
{
template <typename T, typename U>
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 <typename T>
inline VTKM_EXEC_CONT
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
operator()(T a, T b) const
{
return static_cast<T>(a - b);
}
};
struct Multiply
{
template <typename T, typename U>
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 <typename T>
inline VTKM_EXEC_CONT
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
operator()(T a, T b) const
{
return static_cast<T>(a * b);
}
};
struct Divide
{
template <typename T, typename U>
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 <typename T>
inline VTKM_EXEC_CONT
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
operator()(T a, T b) const
{
return static_cast<T>(a / b);
}
};
struct Negate
{
template <typename T>
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 <typename T, vtkm::IdComponent Size>
class VTKM_ALWAYS_EXPORT Vec;
template <typename T>
class VTKM_ALWAYS_EXPORT VecC;
template <typename T>
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 <typename T, typename DerivedClass>
class VTKM_ALWAYS_EXPORT VecBaseCommon
{
public:
using ComponentType = T;
protected:
VecBaseCommon() = default;
VTKM_EXEC_CONT
const DerivedClass& Derived() const { return *static_cast<const DerivedClass*>(this); }
VTKM_EXEC_CONT
DerivedClass& Derived() { return *static_cast<DerivedClass*>(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::IdComponent OtherSize>
VTKM_EXEC_CONT void CopyInto(vtkm::Vec<ComponentType, OtherSize>& 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 <typename OtherVecType>
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 <vtkm::IdComponent Size>
inline VTKM_EXEC_CONT vtkm::Vec<ComponentType, Size> operator+(
const vtkm::Vec<ComponentType, Size>& other) const
{
VTKM_ASSERT(Size == this->NumComponents());
vtkm::Vec<ComponentType, Size> result;
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
result[i] = this->Component(i) + other[i];
}
return result;
}
template <typename OtherClass>
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 <vtkm::IdComponent Size>
inline VTKM_EXEC_CONT vtkm::Vec<ComponentType, Size> operator-(
const vtkm::Vec<ComponentType, Size>& other) const
{
VTKM_ASSERT(Size == this->NumComponents());
vtkm::Vec<ComponentType, Size> result;
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
result[i] = this->Component(i) - other[i];
}
return result;
}
template <typename OtherClass>
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 <vtkm::IdComponent Size>
inline VTKM_EXEC_CONT vtkm::Vec<ComponentType, Size> operator*(
const vtkm::Vec<ComponentType, Size>& other) const
{
vtkm::Vec<ComponentType, Size> result;
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
result[i] = this->Component(i) * other[i];
}
return result;
}
template <typename OtherClass>
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 <vtkm::IdComponent Size>
inline VTKM_EXEC_CONT vtkm::Vec<ComponentType, Size> operator/(
const vtkm::Vec<ComponentType, Size>& other) const
{
vtkm::Vec<ComponentType, Size> result;
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
result[i] = this->Component(i) / other[i];
}
return result;
}
template <typename OtherClass>
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 <typename T, vtkm::IdComponent Size, typename DerivedClass>
class VTKM_ALWAYS_EXPORT VecBase : public vtkm::detail::VecBaseCommon<T, DerivedClass>
{
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 <vtkm::IdComponent Size2 = Size, typename std::enable_if<Size2 != 1, int>::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 <typename... Ts>
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<ComponentType> 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 <typename OtherValueType, typename OtherDerivedType>
VTKM_EXEC_CONT explicit VecBase(const VecBase<OtherValueType, Size, OtherDerivedType>& 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 <typename OtherComponentType, typename OtherClass>
inline VTKM_EXEC_CONT DerivedClass
operator+(const VecBaseCommon<OtherComponentType, OtherClass>& other) const
{
const OtherClass& other_derived = static_cast<const OtherClass&>(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<ComponentType>(other_derived[i]);
}
return result;
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename OtherComponentType, typename OtherClass>
inline VTKM_EXEC_CONT DerivedClass
operator-(const VecBaseCommon<OtherComponentType, OtherClass>& other) const
{
const OtherClass& other_derived = static_cast<const OtherClass&>(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<ComponentType>(other_derived[i]);
}
return result;
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename OtherComponentType, typename OtherClass>
inline VTKM_EXEC_CONT DerivedClass
operator*(const VecBaseCommon<OtherComponentType, OtherClass>& other) const
{
const OtherClass& other_derived = static_cast<const OtherClass&>(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<ComponentType>(other_derived[i]);
}
return result;
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename OtherComponentType, typename OtherClass>
inline VTKM_EXEC_CONT DerivedClass
operator/(const VecBaseCommon<OtherComponentType, OtherClass>& other) const
{
const OtherClass& other_derived = static_cast<const OtherClass&>(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<ComponentType>(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 <typename T, typename DerivedClass>
class VTKM_ALWAYS_EXPORT VecCBase : public vtkm::detail::VecBaseCommon<T, DerivedClass>
{
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 <typename T, vtkm::IdComponent Size>
class VTKM_ALWAYS_EXPORT Vec : public detail::VecBase<T, Size, Vec<T, Size>>
{
using Superclass = detail::VecBase<T, Size, Vec<T, Size>>;
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 <typename... Ts>
constexpr Vec(T value, Ts&&... values)
: Superclass(value, std::forward<Ts>(values)...)
{
}
#endif
inline VTKM_EXEC_CONT void CopyInto(Vec<T, Size>& 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 <typename T>
class VTKM_ALWAYS_EXPORT Vec<T, 0>
{
public:
using ComponentType = T;
static constexpr vtkm::IdComponent NUM_COMPONENTS = 0;
Vec() = default;
VTKM_EXEC_CONT explicit Vec(const ComponentType&) {}
template <typename OtherType>
VTKM_EXEC_CONT Vec(const Vec<OtherType, NUM_COMPONENTS>&)
{
}
VTKM_EXEC_CONT
Vec<ComponentType, NUM_COMPONENTS>& operator=(const Vec<ComponentType, NUM_COMPONENTS>&)
{
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<T, NUM_COMPONENTS>& vtkmNotUsed(other)) const { return true; }
VTKM_EXEC_CONT
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 VTKM_ALWAYS_EXPORT Vec<T, 1> : public detail::VecBase<T, 1, Vec<T, 1>>
{
using Superclass = detail::VecBase<T, 1, Vec<T, 1>>;
public:
Vec() = default;
VTKM_EXEC_CONT constexpr Vec(const T& value)
: Superclass(value)
{
}
template <typename OtherType>
VTKM_EXEC_CONT Vec(const Vec<OtherType, 1>& src)
: Superclass(src)
{
}
};
//-----------------------------------------------------------------------------
// Specializations for common tuple sizes (with special names).
template <typename T>
class VTKM_ALWAYS_EXPORT Vec<T, 2> : public detail::VecBase<T, 2, Vec<T, 2>>
{
using Superclass = detail::VecBase<T, 2, Vec<T, 2>>;
public:
Vec() = default;
VTKM_EXEC_CONT Vec(const T& value)
: Superclass(value)
{
}
template <typename OtherType>
VTKM_EXEC_CONT Vec(const Vec<OtherType, 2>& 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<vtkm::Id, 2>;
/// \brief IdComponent2 corresponds to an index to a local (small) 2-d array or equivalent.
///
using IdComponent2 = vtkm::Vec<vtkm::IdComponent, 2>;
/// \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<vtkm::FloatDefault, 2>.
///
using Vec2f = vtkm::Vec<vtkm::FloatDefault, 2>;
/// \brief Vec2f_32 corresponds to a 2-dimensional vector of 32-bit floating point values.
///
/// It is typedef for vtkm::Vec<vtkm::Float32, 2>.
///
using Vec2f_32 = vtkm::Vec<vtkm::Float32, 2>;
/// \brief Vec2f_64 corresponds to a 2-dimensional vector of 64-bit floating point values.
///
/// It is typedef for vtkm::Vec<vtkm::Float64, 2>.
///
using Vec2f_64 = vtkm::Vec<vtkm::Float64, 2>;
/// \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<vtkm::Id, 2>;
/// \brief Vec2i_8 corresponds to a 2-dimensional vector of 8-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int32, 2>.
///
using Vec2i_8 = vtkm::Vec<vtkm::Int8, 2>;
/// \brief Vec2i_16 corresponds to a 2-dimensional vector of 16-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int32, 2>.
///
using Vec2i_16 = vtkm::Vec<vtkm::Int16, 2>;
/// \brief Vec2i_32 corresponds to a 2-dimensional vector of 32-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int32, 2>.
///
using Vec2i_32 = vtkm::Vec<vtkm::Int32, 2>;
/// \brief Vec2i_64 corresponds to a 2-dimensional vector of 64-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int64, 2>.
///
using Vec2i_64 = vtkm::Vec<vtkm::Int64, 2>;
/// \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<vtkm::UInt64, 2>;
#else
using Vec2ui = vtkm::Vec<vtkm::UInt32, 2>;
#endif
/// \brief Vec2ui_8 corresponds to a 2-dimensional vector of 8-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt32, 2>.
///
using Vec2ui_8 = vtkm::Vec<vtkm::UInt8, 2>;
/// \brief Vec2ui_16 corresponds to a 2-dimensional vector of 16-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt32, 2>.
///
using Vec2ui_16 = vtkm::Vec<vtkm::UInt16, 2>;
/// \brief Vec2ui_32 corresponds to a 2-dimensional vector of 32-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt32, 2>.
///
using Vec2ui_32 = vtkm::Vec<vtkm::UInt32, 2>;
/// \brief Vec2ui_64 corresponds to a 2-dimensional vector of 64-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt64, 2>.
///
using Vec2ui_64 = vtkm::Vec<vtkm::UInt64, 2>;
template <typename T>
class VTKM_ALWAYS_EXPORT Vec<T, 3> : public detail::VecBase<T, 3, Vec<T, 3>>
{
using Superclass = detail::VecBase<T, 3, Vec<T, 3>>;
public:
Vec() = default;
VTKM_EXEC_CONT Vec(const T& value)
: Superclass(value)
{
}
template <typename OtherType>
VTKM_EXEC_CONT Vec(const Vec<OtherType, 3>& 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<vtkm::Id, 3>;
/// \brief IdComponent2 corresponds to an index to a local (small) 3-d array or equivalent.
///
using IdComponent3 = vtkm::Vec<vtkm::IdComponent, 3>;
/// \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<vtkm::FloatDefault, 3>.
///
using Vec3f = vtkm::Vec<vtkm::FloatDefault, 3>;
/// \brief Vec3f_32 corresponds to a 3-dimensional vector of 32-bit floating point values.
///
/// It is typedef for vtkm::Vec<vtkm::Float32, 3>.
///
using Vec3f_32 = vtkm::Vec<vtkm::Float32, 3>;
/// \brief Vec3f_64 corresponds to a 3-dimensional vector of 64-bit floating point values.
///
/// It is typedef for vtkm::Vec<vtkm::Float64, 3>.
///
using Vec3f_64 = vtkm::Vec<vtkm::Float64, 3>;
/// \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<vtkm::Id, 3>;
/// \brief Vec3i_8 corresponds to a 3-dimensional vector of 8-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int32, 3>.
///
using Vec3i_8 = vtkm::Vec<vtkm::Int8, 3>;
/// \brief Vec3i_16 corresponds to a 3-dimensional vector of 16-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int32, 3>.
///
using Vec3i_16 = vtkm::Vec<vtkm::Int16, 3>;
/// \brief Vec3i_32 corresponds to a 3-dimensional vector of 32-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int32, 3>.
///
using Vec3i_32 = vtkm::Vec<vtkm::Int32, 3>;
/// \brief Vec3i_64 corresponds to a 3-dimensional vector of 64-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int64, 3>.
///
using Vec3i_64 = vtkm::Vec<vtkm::Int64, 3>;
/// \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<vtkm::UInt64, 3>;
#else
using Vec3ui = vtkm::Vec<vtkm::UInt32, 3>;
#endif
/// \brief Vec3ui_8 corresponds to a 3-dimensional vector of 8-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt32, 3>.
///
using Vec3ui_8 = vtkm::Vec<vtkm::UInt8, 3>;
/// \brief Vec3ui_16 corresponds to a 3-dimensional vector of 16-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt32, 3>.
///
using Vec3ui_16 = vtkm::Vec<vtkm::UInt16, 3>;
/// \brief Vec3ui_32 corresponds to a 3-dimensional vector of 32-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt32, 3>.
///
using Vec3ui_32 = vtkm::Vec<vtkm::UInt32, 3>;
/// \brief Vec3ui_64 corresponds to a 3-dimensional vector of 64-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt64, 3>.
///
using Vec3ui_64 = vtkm::Vec<vtkm::UInt64, 3>;
template <typename T>
class VTKM_ALWAYS_EXPORT Vec<T, 4> : public detail::VecBase<T, 4, Vec<T, 4>>
{
using Superclass = detail::VecBase<T, 4, Vec<T, 4>>;
public:
Vec() = default;
VTKM_EXEC_CONT Vec(const T& value)
: Superclass(value)
{
}
template <typename OtherType>
VTKM_EXEC_CONT Vec(const Vec<OtherType, 4>& 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<vtkm::Id, 4>;
/// \brief IdComponent4 corresponds to an index to a local (small) 4-d array or equivalent.
///
using IdComponent4 = vtkm::Vec<vtkm::IdComponent, 4>;
/// \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<vtkm::FloatDefault, 4>.
///
using Vec4f = vtkm::Vec<vtkm::FloatDefault, 4>;
/// \brief Vec4f_32 corresponds to a 4-dimensional vector of 32-bit floating point values.
///
/// It is typedef for vtkm::Vec<vtkm::Float32, 4>.
///
using Vec4f_32 = vtkm::Vec<vtkm::Float32, 4>;
/// \brief Vec4f_64 corresponds to a 4-dimensional vector of 64-bit floating point values.
///
/// It is typedef for vtkm::Vec<vtkm::Float64, 4>.
///
using Vec4f_64 = vtkm::Vec<vtkm::Float64, 4>;
/// \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<vtkm::Id, 4>;
/// \brief Vec4i_8 corresponds to a 4-dimensional vector of 8-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int32, 4>.
///
using Vec4i_8 = vtkm::Vec<vtkm::Int8, 4>;
/// \brief Vec4i_16 corresponds to a 4-dimensional vector of 16-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int32, 4>.
///
using Vec4i_16 = vtkm::Vec<vtkm::Int16, 4>;
/// \brief Vec4i_32 corresponds to a 4-dimensional vector of 32-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int32, 4>.
///
using Vec4i_32 = vtkm::Vec<vtkm::Int32, 4>;
/// \brief Vec4i_64 corresponds to a 4-dimensional vector of 64-bit integer values.
///
/// It is typedef for vtkm::Vec<vtkm::Int64, 4>.
///
using Vec4i_64 = vtkm::Vec<vtkm::Int64, 4>;
/// \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<vtkm::UInt64, 4>;
#else
using Vec4ui = vtkm::Vec<vtkm::UInt32, 4>;
#endif
/// \brief Vec4ui_8 corresponds to a 4-dimensional vector of 8-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt32, 4>.
///
using Vec4ui_8 = vtkm::Vec<vtkm::UInt8, 4>;
/// \brief Vec4ui_16 corresponds to a 4-dimensional vector of 16-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt32, 4>.
///
using Vec4ui_16 = vtkm::Vec<vtkm::UInt16, 4>;
/// \brief Vec4ui_32 corresponds to a 4-dimensional vector of 32-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt32, 4>.
///
using Vec4ui_32 = vtkm::Vec<vtkm::UInt32, 4>;
/// \brief Vec4ui_64 corresponds to a 4-dimensional vector of 64-bit unsigned integer values.
///
/// It is typedef for vtkm::Vec<vtkm::UInt64, 4>.
///
using Vec4ui_64 = vtkm::Vec<vtkm::UInt64, 4>;
/// Initializes and returns a Vec containing all the arguments. The arguments should all be the
/// same type or compile issues will occur.
///
template <typename T, typename... Ts>
VTKM_EXEC_CONT constexpr vtkm::Vec<T, vtkm::IdComponent(sizeof...(Ts) + 1)> make_Vec(T value0,
Ts&&... args)
{
return vtkm::Vec<T, vtkm::IdComponent(sizeof...(Ts) + 1)>(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 <tt>VecC<const vtkm::Id></tt>. If you want a
/// non-mutable \c VecC, the \c VecCConst class (e.g.
/// <tt>VecCConst<vtkm::Id></tt>).
///
template <typename T>
class VTKM_ALWAYS_EXPORT VecC : public detail::VecCBase<T, VecC<T>>
{
using Superclass = detail::VecCBase<T, VecC<T>>;
VTKM_STATIC_ASSERT_MSG(std::is_const<T>::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::IdComponent Size>
VTKM_EXEC_CONT VecC(vtkm::Vec<T, Size>& src)
: Components(src.GetPointer())
, NumberOfComponents(Size)
{
}
VTKM_EXEC_CONT
explicit VecC(T& src)
: Components(&src)
, NumberOfComponents(1)
{
}
VTKM_EXEC_CONT
VecC(const VecC<T>& 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<T>& operator=(const VecC<T>& 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 <typename T>
class VTKM_ALWAYS_EXPORT VecCConst : public detail::VecCBase<T, VecCConst<T>>
{
using Superclass = detail::VecCBase<T, VecCConst<T>>;
VTKM_STATIC_ASSERT_MSG(std::is_const<T>::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::IdComponent Size>
VTKM_EXEC_CONT VecCConst(const vtkm::Vec<T, Size>& src)
: Components(src.GetPointer())
, NumberOfComponents(Size)
{
}
VTKM_EXEC_CONT
explicit VecCConst(const T& src)
: Components(&src)
, NumberOfComponents(1)
{
}
VTKM_EXEC_CONT
VecCConst(const VecCConst<T>& src)
: Components(src.Components)
, NumberOfComponents(src.NumberOfComponents)
{
}
VTKM_EXEC_CONT
VecCConst(const VecC<T>& 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<T>&) = delete;
void operator+=(const VecCConst<T>&) = delete;
void operator-=(const VecCConst<T>&) = delete;
void operator*=(const VecCConst<T>&) = delete;
void operator/=(const VecCConst<T>&) = delete;
};
/// Creates a \c VecC from an input array.
///
template <typename T>
static inline VTKM_EXEC_CONT vtkm::VecC<T> make_VecC(T* array, vtkm::IdComponent size)
{
return vtkm::VecC<T>(array, size);
}
/// Creates a \c VecCConst from a constant input array.
///
template <typename T>
static inline VTKM_EXEC_CONT vtkm::VecCConst<T> make_VecC(const T* array, vtkm::IdComponent size)
{
return vtkm::VecCConst<T>(array, size);
}
namespace detail
{
template <typename T>
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 <typename T, vtkm::IdComponent Size>
static inline VTKM_EXEC_CONT auto vec_dot(const vtkm::Vec<T, Size>& a, const vtkm::Vec<T, Size>& 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 <typename T>
static inline VTKM_EXEC_CONT auto Dot(const T& a, const T& b)
{
return detail::vec_dot(a, b);
}
template <typename T>
static inline VTKM_EXEC_CONT auto Dot(const vtkm::Vec<T, 2>& a, const vtkm::Vec<T, 2>& b)
{
return (a[0] * b[0]) + (a[1] * b[1]);
}
template <typename T>
static inline VTKM_EXEC_CONT auto Dot(const vtkm::Vec<T, 3>& a, const vtkm::Vec<T, 3>& b)
{
return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
}
template <typename T>
static inline VTKM_EXEC_CONT auto Dot(const vtkm::Vec<T, 4>& a, const vtkm::Vec<T, 4>& 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 <typename T>
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 <typename T>
static inline VTKM_EXEC_CONT auto dot(const vtkm::Vec<T, 2>& a, const vtkm::Vec<T, 2>& b)
{
return vtkm::Dot(a, b);
}
template <typename T>
static inline VTKM_EXEC_CONT auto dot(const vtkm::Vec<T, 3>& a, const vtkm::Vec<T, 3>& b)
{
return vtkm::Dot(a, b);
}
template <typename T>
static inline VTKM_EXEC_CONT auto dot(const vtkm::Vec<T, 4>& a, const vtkm::Vec<T, 4>& b)
{
return vtkm::Dot(a, b);
}
// ^============ LEGACY =============^
template <typename T, vtkm::IdComponent Size>
inline VTKM_EXEC_CONT 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>
inline VTKM_EXEC_CONT T ReduceSum(const vtkm::Vec<T, 2>& a)
{
return a[0] + a[1];
}
template <typename T>
inline VTKM_EXEC_CONT T ReduceSum(const vtkm::Vec<T, 3>& a)
{
return a[0] + a[1] + a[2];
}
template <typename T>
inline VTKM_EXEC_CONT T ReduceSum(const vtkm::Vec<T, 4>& a)
{
return a[0] + a[1] + a[2] + a[3];
}
template <typename T, vtkm::IdComponent Size>
inline VTKM_EXEC_CONT 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>
inline VTKM_EXEC_CONT T ReduceProduct(const vtkm::Vec<T, 2>& a)
{
return a[0] * a[1];
}
template <typename T>
inline VTKM_EXEC_CONT T ReduceProduct(const vtkm::Vec<T, 3>& a)
{
return a[0] * a[1] * a[2];
}
template <typename T>
inline VTKM_EXEC_CONT T ReduceProduct(const vtkm::Vec<T, 4>& 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 <typename U, typename V>
struct Pair;
/// Helper function for printing out vectors during testing.
///
template <typename T, vtkm::IdComponent Size>
inline VTKM_CONT 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>
inline VTKM_EXEC_CONT std::ostream& operator<<(std::ostream& stream, const vtkm::Pair<T, U>& vec)
{
return stream << "[" << vec.first << "," << vec.second << "]";
}
} // End of namespace vtkm
#include <vtkm/internal/VecOperators.h>
// Declared inside of vtkm namespace so that the operator work with ADL lookup
#endif //vtk_m_Types_h