mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
constexpr construction for Vec classes
Vec class objects can now be constructed during compile-time as constant expressions by calling Vec( T, ... ) constructors or through brace-initialization. Constant expression using fill constructor and nested vectors of sizes greater than 4 are not supported yet. Changes made to WrappedOperators.h for resolving overload ambiguities in Vec construction and typecasting. Appropriate test cases were added to UnitTestTypes.cxx. Addresses issue #199.
This commit is contained in:
parent
7de4bba7e9
commit
947496550e
89
vtkm/Types.h
89
vtkm/Types.h
@ -613,11 +613,12 @@ public:
|
||||
using ComponentType = T;
|
||||
static constexpr vtkm::IdComponent NUM_COMPONENTS = Size;
|
||||
|
||||
protected:
|
||||
VecBase() = default;
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
explicit VecBase(const ComponentType& value)
|
||||
// The enable_if predicate will disable this constructor for Size=1 so that
|
||||
// the variadic constructor constexpr VecBase(T, Ts&&...) is called instead.
|
||||
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)
|
||||
{
|
||||
@ -625,6 +626,13 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
VTKM_EXEC_CONT constexpr VecBase(ComponentType value0, Ts&&... values)
|
||||
: Components{ value0, values... }
|
||||
{
|
||||
VTKM_STATIC_ASSERT(sizeof...(Ts) + 1 == Size);
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
VecBase(std::initializer_list<ComponentType> values)
|
||||
{
|
||||
@ -812,21 +820,15 @@ public:
|
||||
static constexpr vtkm::IdComponent NUM_COMPONENTS = Size;
|
||||
#endif
|
||||
|
||||
using Superclass::Superclass;
|
||||
Vec() = default;
|
||||
VTKM_EXEC_CONT explicit Vec(const T& value)
|
||||
: Superclass(value)
|
||||
{
|
||||
}
|
||||
VTKM_EXEC_CONT Vec(std::initializer_list<T> values)
|
||||
: Superclass(values)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename OtherType>
|
||||
VTKM_EXEC_CONT explicit Vec(const Vec<OtherType, Size>& src)
|
||||
: Superclass(src)
|
||||
#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; }
|
||||
};
|
||||
@ -876,14 +878,10 @@ class VTKM_ALWAYS_EXPORT Vec<T, 1> : public detail::VecBase<T, 1, Vec<T, 1>>
|
||||
|
||||
public:
|
||||
Vec() = default;
|
||||
VTKM_EXEC_CONT explicit Vec(const T& value)
|
||||
VTKM_EXEC_CONT constexpr Vec(const T& value)
|
||||
: Superclass(value)
|
||||
{
|
||||
}
|
||||
VTKM_EXEC_CONT Vec(std::initializer_list<T> values)
|
||||
: Superclass(values)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename OtherType>
|
||||
VTKM_EXEC_CONT Vec(const Vec<OtherType, 1>& src)
|
||||
@ -902,14 +900,10 @@ class VTKM_ALWAYS_EXPORT Vec<T, 2> : public detail::VecBase<T, 2, Vec<T, 2>>
|
||||
|
||||
public:
|
||||
Vec() = default;
|
||||
VTKM_EXEC_CONT explicit Vec(const T& value)
|
||||
VTKM_EXEC_CONT Vec(const T& value)
|
||||
: Superclass(value)
|
||||
{
|
||||
}
|
||||
VTKM_EXEC_CONT Vec(std::initializer_list<T> values)
|
||||
: Superclass(values)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename OtherType>
|
||||
VTKM_EXEC_CONT Vec(const Vec<OtherType, 2>& src)
|
||||
@ -918,10 +912,9 @@ public:
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
Vec(const T& x, const T& y)
|
||||
constexpr Vec(const T& x, const T& y)
|
||||
: Superclass(x, y)
|
||||
{
|
||||
this->Components[0] = x;
|
||||
this->Components[1] = y;
|
||||
}
|
||||
};
|
||||
|
||||
@ -935,14 +928,10 @@ class VTKM_ALWAYS_EXPORT Vec<T, 3> : public detail::VecBase<T, 3, Vec<T, 3>>
|
||||
|
||||
public:
|
||||
Vec() = default;
|
||||
VTKM_EXEC_CONT explicit Vec(const T& value)
|
||||
VTKM_EXEC_CONT Vec(const T& value)
|
||||
: Superclass(value)
|
||||
{
|
||||
}
|
||||
VTKM_EXEC_CONT Vec(std::initializer_list<T> values)
|
||||
: Superclass(values)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename OtherType>
|
||||
VTKM_EXEC_CONT Vec(const Vec<OtherType, 3>& src)
|
||||
@ -951,11 +940,9 @@ public:
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
Vec(const T& x, const T& y, const T& z)
|
||||
constexpr Vec(const T& x, const T& y, const T& z)
|
||||
: Superclass(x, y, z)
|
||||
{
|
||||
this->Components[0] = x;
|
||||
this->Components[1] = y;
|
||||
this->Components[2] = z;
|
||||
}
|
||||
};
|
||||
|
||||
@ -970,14 +957,10 @@ class VTKM_ALWAYS_EXPORT Vec<T, 4> : public detail::VecBase<T, 4, Vec<T, 4>>
|
||||
|
||||
public:
|
||||
Vec() = default;
|
||||
VTKM_EXEC_CONT explicit Vec(const T& value)
|
||||
VTKM_EXEC_CONT Vec(const T& value)
|
||||
: Superclass(value)
|
||||
{
|
||||
}
|
||||
VTKM_EXEC_CONT Vec(std::initializer_list<T> values)
|
||||
: Superclass(values)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename OtherType>
|
||||
VTKM_EXEC_CONT Vec(const Vec<OtherType, 4>& src)
|
||||
@ -986,32 +969,20 @@ public:
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
Vec(const T& x, const T& y, const T& z, const T& w)
|
||||
constexpr Vec(const T& x, const T& y, const T& z, const T& w)
|
||||
: Superclass(x, y, z, w)
|
||||
{
|
||||
this->Components[0] = x;
|
||||
this->Components[1] = y;
|
||||
this->Components[2] = z;
|
||||
this->Components[3] = w;
|
||||
}
|
||||
};
|
||||
|
||||
/// Initializes and returns a Vec initialized by the given intializer_list. Due to limitations in
|
||||
/// C++11, you also have to specify the length of the Vec.
|
||||
///
|
||||
template <vtkm::IdComponent Size, typename T>
|
||||
VTKM_EXEC_CONT vtkm::Vec<T, Size> make_Vec(std::initializer_list<T> values)
|
||||
{
|
||||
return vtkm::Vec<T, Size>(values);
|
||||
}
|
||||
|
||||
/// 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 vtkm::Vec<T, vtkm::IdComponent(sizeof...(Ts) + 1)> make_Vec(const T& value0,
|
||||
const Ts&... values)
|
||||
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, values... });
|
||||
return vtkm::Vec<T, vtkm::IdComponent(sizeof...(Ts) + 1)>(value0, T(args)...);
|
||||
}
|
||||
|
||||
/// \brief A Vec-like representation for short arrays.
|
||||
|
@ -111,19 +111,25 @@ struct WrappedBinaryOperator
|
||||
template <typename U>
|
||||
VTKM_EXEC T operator()(const T& x, const PortalValue<U>& y) const
|
||||
{
|
||||
return m_f(x, (T)y);
|
||||
// to support proper implicit conversion, and avoid overload
|
||||
// ambiguities.
|
||||
T conv_y = y;
|
||||
return m_f(x, conv_y);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
VTKM_EXEC T operator()(const PortalValue<U>& x, const T& y) const
|
||||
{
|
||||
return m_f((T)x, y);
|
||||
T conv_x = x;
|
||||
return m_f(conv_x, y);
|
||||
}
|
||||
|
||||
template <typename U, typename V>
|
||||
VTKM_EXEC T operator()(const PortalValue<U>& x, const PortalValue<V>& y) const
|
||||
{
|
||||
return m_f((T)x, (T)y);
|
||||
T conv_x = x;
|
||||
T conv_y = y;
|
||||
return m_f(conv_x, conv_y);
|
||||
}
|
||||
|
||||
VTKM_EXEC T operator()(const T* const x, const T& y) const { return m_f(*x, y); }
|
||||
|
@ -442,6 +442,19 @@ void TypeTest(const vtkm::Vec<ComponentType, Size>&)
|
||||
GeneralVecTypeTest(vtkm::Vec<ComponentType, Size>());
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
void TypeTest(const vtkm::Vec<Scalar, 1>&)
|
||||
{
|
||||
using Vector = vtkm::Vec<Scalar, 1>;
|
||||
std::cout << "Checking constexpr construction for Vec1." << std::endl;
|
||||
|
||||
constexpr Vector constExprVec1(Scalar(1));
|
||||
constexpr Vector constExprVec2 = { Scalar(1) };
|
||||
constexpr Vector madeVec = vtkm::make_Vec(Scalar(1));
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec1, madeVec), "constexpr Vec1 failed equality test.");
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec2, madeVec), "constexpr Vec1 failed equality test.");
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
void TypeTest(const vtkm::Vec<Scalar, 2>&)
|
||||
{
|
||||
@ -454,8 +467,6 @@ void TypeTest(const vtkm::Vec<Scalar, 2>&)
|
||||
Scalar s = 5;
|
||||
|
||||
VTKM_TEST_ASSERT(a == vtkm::make_Vec(Scalar(2), Scalar(4)), "make_Vec creates different object.");
|
||||
VTKM_TEST_ASSERT(a == vtkm::make_Vec<2>({ Scalar(2), Scalar(4) }),
|
||||
"make_Vec creates different object.");
|
||||
VTKM_TEST_ASSERT((a == vtkm::Vec<Scalar, 2>{ Scalar(2), Scalar(4) }),
|
||||
"Construct with initializer list creates different object.");
|
||||
|
||||
@ -507,6 +518,18 @@ void TypeTest(const vtkm::Vec<Scalar, 2>&)
|
||||
|
||||
VTKM_TEST_ASSERT((c != a), "operator != wrong");
|
||||
VTKM_TEST_ASSERT((a != c), "operator != wrong");
|
||||
|
||||
std::cout << "Checking constexpr construction for Vec2." << std::endl;
|
||||
constexpr Vector constExprVec1(Scalar(1), Scalar(2));
|
||||
constexpr Vector constExprVec2 = { Scalar(1), Scalar(2) };
|
||||
constexpr Vector madeVec = vtkm::make_Vec(Scalar(1), Scalar(2));
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec1, madeVec), "constexpr Vec2 failed equality test.");
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec2, madeVec), "constexpr Vec2 failed equality test.");
|
||||
|
||||
// Check fill constructor.
|
||||
Vector fillVec1 = { Scalar(8) };
|
||||
Vector fillVec2(Scalar(8), Scalar(8));
|
||||
VTKM_TEST_ASSERT(test_equal(fillVec1, fillVec2), "fill ctor Vec2 failed equality test.");
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
@ -522,8 +545,6 @@ void TypeTest(const vtkm::Vec<Scalar, 3>&)
|
||||
|
||||
VTKM_TEST_ASSERT(a == vtkm::make_Vec(Scalar(2), Scalar(4), Scalar(6)),
|
||||
"make_Vec creates different object.");
|
||||
VTKM_TEST_ASSERT(a == vtkm::make_Vec<3>({ Scalar(2), Scalar(4), Scalar(6) }),
|
||||
"make_Vec creates different object.");
|
||||
VTKM_TEST_ASSERT((a == vtkm::Vec<Scalar, 3>{ Scalar(2), Scalar(4), Scalar(6) }),
|
||||
"Construct with initializer list creates different object.");
|
||||
|
||||
@ -576,6 +597,18 @@ void TypeTest(const vtkm::Vec<Scalar, 3>&)
|
||||
|
||||
VTKM_TEST_ASSERT((c != a), "operator != wrong");
|
||||
VTKM_TEST_ASSERT((a != c), "operator != wrong");
|
||||
|
||||
std::cout << "Checking constexpr construction for Vec3." << std::endl;
|
||||
constexpr Vector constExprVec1(Scalar(1), Scalar(2), Scalar(3));
|
||||
constexpr Vector constExprVec2 = { Scalar(1), Scalar(2), Scalar(3) };
|
||||
constexpr Vector madeVec = vtkm::make_Vec(Scalar(1), Scalar(2), Scalar(3));
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec1, madeVec), "constexpr Vec3 failed equality test.");
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec2, madeVec), "constexpr Vec3 failed equality test.");
|
||||
|
||||
// Check fill constructor.
|
||||
Vector fillVec1 = { Scalar(8) };
|
||||
Vector fillVec2(Scalar(8), Scalar(8), Scalar(8));
|
||||
VTKM_TEST_ASSERT(test_equal(fillVec1, fillVec2), "fill ctor Vec3 failed equality test.");
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
@ -591,8 +624,6 @@ void TypeTest(const vtkm::Vec<Scalar, 4>&)
|
||||
|
||||
VTKM_TEST_ASSERT(a == vtkm::make_Vec(Scalar(2), Scalar(4), Scalar(6), Scalar(8)),
|
||||
"make_Vec creates different object.");
|
||||
VTKM_TEST_ASSERT(a == vtkm::make_Vec<4>({ Scalar(2), Scalar(4), Scalar(6), Scalar(8) }),
|
||||
"make_Vec creates different object.");
|
||||
VTKM_TEST_ASSERT((a == vtkm::Vec<Scalar, 4>{ Scalar(2), Scalar(4), Scalar(6), Scalar(8) }),
|
||||
"Construct with initializer list creates different object.");
|
||||
|
||||
@ -645,6 +676,41 @@ void TypeTest(const vtkm::Vec<Scalar, 4>&)
|
||||
|
||||
VTKM_TEST_ASSERT((c != a), "operator != wrong");
|
||||
VTKM_TEST_ASSERT((a != c), "operator != wrong");
|
||||
|
||||
std::cout << "Checking constexpr construction for Vec4." << std::endl;
|
||||
constexpr Vector constExprVec1(Scalar(1), Scalar(2), Scalar(3), Scalar(4));
|
||||
constexpr Vector constExprVec2 = { Scalar(1), Scalar(2), Scalar(3), Scalar(4) };
|
||||
constexpr Vector madeVec = vtkm::make_Vec(Scalar(1), Scalar(2), Scalar(3), Scalar(4));
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec1, madeVec), "constexpr Vec4 failed equality test.");
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec2, madeVec), "constexpr Vec4 failed equality test.");
|
||||
|
||||
// Check fill constructor.
|
||||
Vector fillVec1 = { Scalar(8) };
|
||||
Vector fillVec2(Scalar(8), Scalar(8), Scalar(8), Scalar(8));
|
||||
VTKM_TEST_ASSERT(test_equal(fillVec1, fillVec2), "fill ctor Vec4 failed equality test.");
|
||||
|
||||
Scalar values[4] = { Scalar(1), Scalar(1), Scalar(1), Scalar(1) };
|
||||
Vector lvalVec1 = vtkm::make_Vec(values[0], values[1], values[2], values[3]);
|
||||
Vector lvalVec2 = Vector(values[0], values[1], values[2], values[3]);
|
||||
VTKM_TEST_ASSERT(test_equal(lvalVec1, lvalVec2), "lvalue ctor Vec4 failed equality test.");
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
void TypeTest(const vtkm::Vec<Scalar, 6>&)
|
||||
{
|
||||
using Vector = vtkm::Vec<Scalar, 6>;
|
||||
std::cout << "Checking constexpr construction for Vec6." << std::endl;
|
||||
constexpr Vector constExprVec1(Scalar(1), Scalar(2), Scalar(3), Scalar(4), Scalar(5), Scalar(6));
|
||||
Vector braceVec = { Scalar(1), Scalar(2), Scalar(3), Scalar(4), Scalar(5), Scalar(6) };
|
||||
constexpr Vector madeVec =
|
||||
vtkm::make_Vec(Scalar(1), Scalar(2), Scalar(3), Scalar(4), Scalar(5), Scalar(6));
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec1, madeVec), "constexpr Vec6 failed equality test.");
|
||||
VTKM_TEST_ASSERT(test_equal(braceVec, madeVec), "constexpr Vec6 failed equality test.");
|
||||
|
||||
// Check fill constructor.
|
||||
Vector fillVec1 = { Scalar(8) };
|
||||
Vector fillVec2 = Vector(Scalar(8), Scalar(8), Scalar(8), Scalar(8), Scalar(8), Scalar(8));
|
||||
VTKM_TEST_ASSERT(test_equal(fillVec1, fillVec2), "fill ctor Vec6 failed equality test.");
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
@ -759,6 +825,40 @@ void TypeTest(vtkm::Vec<vtkm::Vec<Scalar, 2>, 3>)
|
||||
//Vector vec1 = { 0, 1, 2 };
|
||||
//Vector vec2 = { 0, 1 };
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "Checking constexpr construction for Vec3<Vec2>." << std::endl;
|
||||
constexpr Vector constExprVec1(
|
||||
vtkm::Vec<Scalar, 2>(1, 2), vtkm::Vec<Scalar, 2>(1, 2), vtkm::Vec<Scalar, 2>(1, 2));
|
||||
constexpr Vector constExprVec2 = { { 1, 2 }, { 1, 2 }, { 1, 2 } };
|
||||
constexpr Vector madeVec = vtkm::make_Vec(vtkm::make_Vec(Scalar(1), Scalar(2)),
|
||||
vtkm::make_Vec(Scalar(1), Scalar(2)),
|
||||
vtkm::make_Vec(Scalar(1), Scalar(2)));
|
||||
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec1, madeVec),
|
||||
"constexpr Vec3<Vec2> failed equality test.");
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec2, madeVec),
|
||||
"constexpr Vec3<Vec2> failed equality test.");
|
||||
|
||||
// Check fill constructor.
|
||||
Vector fillVec1 = { { Scalar(1), Scalar(2) } };
|
||||
Vector fillVec2(
|
||||
vtkm::Vec<Scalar, 2>(1, 2), vtkm::Vec<Scalar, 2>(1, 2), vtkm::Vec<Scalar, 2>(1, 2));
|
||||
VTKM_TEST_ASSERT(test_equal(fillVec1, fillVec2), "fill ctor Vec3ofVec2 failed equality test.");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
void TypeTest(vtkm::Vec<vtkm::Vec<Scalar, 2>, 5>)
|
||||
{
|
||||
using Vector = vtkm::Vec<vtkm::Vec<Scalar, 2>, 5>;
|
||||
Vector braceVec = { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 } };
|
||||
constexpr Vector constExprVec = vtkm::make_Vec(vtkm::make_Vec(Scalar(1), Scalar(1)),
|
||||
vtkm::make_Vec(Scalar(2), Scalar(2)),
|
||||
vtkm::make_Vec(Scalar(3), Scalar(3)),
|
||||
vtkm::make_Vec(Scalar(4), Scalar(4)),
|
||||
vtkm::make_Vec(Scalar(5), Scalar(5)));
|
||||
VTKM_TEST_ASSERT(test_equal(constExprVec, braceVec), "Vec5<Vec2> failed equality test.");
|
||||
}
|
||||
|
||||
struct TypeTestFunctor
|
||||
@ -775,9 +875,11 @@ struct TypesToTest : vtkm::ListTagJoin<vtkm::testing::Testing::TypeListTagExempl
|
||||
vtkm::Vec<vtkm::Id, 4>,
|
||||
vtkm::Vec<unsigned char, 4>,
|
||||
vtkm::Vec<vtkm::Id, 1>,
|
||||
vtkm::Vec<vtkm::Id, 2>,
|
||||
vtkm::Vec<vtkm::Float64, 1>,
|
||||
vtkm::Vec<vtkm::Id2, 3>,
|
||||
vtkm::Vec<vtkm::Vec<vtkm::Float32, 2>, 3>>>
|
||||
vtkm::Vec<vtkm::Vec<vtkm::Float32, 2>, 3>,
|
||||
vtkm::Vec<vtkm::Vec<vtkm::Float32, 2>, 5>>>
|
||||
{
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user