mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Add support for initializer lists in Vec
Add constructors to the `vtkm::Vec` classes that accept `std::initializer_list`. The main advantage of this addition is that it makes it much easier to initialize `Vec`s of arbitrary length.
This commit is contained in:
parent
2b10108a32
commit
ae8d994d21
86
docs/changelog/vec-initializer-lists.md
Normal file
86
docs/changelog/vec-initializer-lists.md
Normal file
@ -0,0 +1,86 @@
|
||||
# Support initializer lists for Vec
|
||||
|
||||
Add constructors to the `vtkm::Vec` classes that accept `std::initializer_list`. The
|
||||
main advantage of this addition is that it makes it much easier to initialize `Vec`s
|
||||
of arbitrary length.
|
||||
|
||||
Although previously some `Vec` classes could be constructed with values listed in
|
||||
their parameters, that only worked for initializes up to size 4.
|
||||
|
||||
``` cpp
|
||||
vtkm::Vec<vtkm::Float64, 3> vec1{1.1, 2.2, 3.3}; // New better initializer
|
||||
|
||||
vtkm::Vec<vtkm::Float64, 3> vec2 = {1.1, 2.2, 3.3}; // Nice syntax also supported by
|
||||
// initializer lists.
|
||||
|
||||
vtkm::Vec<vtkm::Float64, 3> vec3(1.1, 2.2, 3.3); // Old style that still works but
|
||||
// probably should be deprecated.
|
||||
```
|
||||
|
||||
The nice thing about the initializer list implementation is that it works for any
|
||||
size `Vec`. That keeps us from jumping through hoops for larger `Vec`s.
|
||||
|
||||
``` cpp
|
||||
vtkm::Vec<vtkm::Float64, 5> vec1{1.1, 2.2, 3.3, 4.4, 5.5}; // Works fine.
|
||||
|
||||
vtkm::Vec<vtkm::Float64, 5> vec2(1.1, 2.2, 3.3, 4.4, 5.5); // ERROR! This constructor
|
||||
// not implemented!
|
||||
```
|
||||
|
||||
`vtkm::make_Vec` is also updated to support an arbitrary number initial values.
|
||||
|
||||
``` cpp
|
||||
// Creates a vtkm::Vec<vtkm::Float64, 5>
|
||||
auto vec = vtkm::make_Vec(1.1, 2.2, 3.3, 4.4, 5.5);
|
||||
```
|
||||
|
||||
This is super convenient when dealing with variadic function arguments.
|
||||
|
||||
``` cpp
|
||||
template <typename... Ts>
|
||||
void ExampleVariadicFunction(const Ts&... params)
|
||||
{
|
||||
auto vec = vtkm::make_Vec(params);
|
||||
```
|
||||
|
||||
Of course, this assumes that the type of all the parameters is the same. If not, you
|
||||
could run into compiler trouble.
|
||||
|
||||
There is also a version of `vtkm::make_Vec` that accepts an `std::initializer_list`,
|
||||
but it is not very useful because you have to separately specify the length of the
|
||||
`Vec` (due to some limitations of `std::initializer_list` in C++11).
|
||||
|
||||
``` cpp
|
||||
// Creates a vtkm::Vec<vtkm::Float64, 3>
|
||||
auto vec1 = vtkm::make_Vec<3>({1.1, 2.2, 3.3});
|
||||
|
||||
// Creates exactly the same thing
|
||||
auto vec2 = vtkm::Vec<vtkm::Float64, 3>{1.1, 2.2, 3.3};
|
||||
```
|
||||
|
||||
A limitation of the initializer list constructor is that the compiler has no way to
|
||||
check the length of the list or force it to a particular length. Thus it is entirely
|
||||
possible to construct a `Vec` with the wrong number of arguments. Or, more to the
|
||||
point, the compiler will let you do it, but there is an assert in the constructor to
|
||||
correct for that. (Of course, asserts are not compiled in release builds.)
|
||||
|
||||
``` cpp
|
||||
// This will compile, but it's results are undefined when it is run.
|
||||
// In debug builds, it will fail an assert.
|
||||
vtkm::Vec<vtkm::Float64, 3> vec{1.1, 1.2};
|
||||
```
|
||||
|
||||
There is a distinction between the initializer list constructors and all other types
|
||||
of constructors. Specifically, the initializer list constructor sets each component
|
||||
to each value in the initializer list (much like initializing an array). In
|
||||
particular, there is a considerable difference between the initializer list
|
||||
constructor and the constructor taking one value that fills up the array. Don't use
|
||||
the wrong one.
|
||||
|
||||
``` cpp
|
||||
// This creates a vector filled with [3.14, 3.14, 3.14]
|
||||
vtkm::Vec<vtkm::Float64, 3> vec1(3.14);
|
||||
|
||||
// The result of this is underfined. In debug builds, it will fail an assert.
|
||||
vtkm::Vec<vtkm::Float64, 3> vec1{3.14};
|
||||
```
|
59
vtkm/Types.h
59
vtkm/Types.h
@ -625,6 +625,19 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
VecBase(std::initializer_list<ComponentType> values)
|
||||
{
|
||||
VTKM_ASSERT((values.size() == NUM_COMPONENTS) &&
|
||||
"Vec object initialized wrong number of components.");
|
||||
ComponentType* dest = this->Components;
|
||||
for (auto src = values.begin(); 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
|
||||
@ -792,6 +805,10 @@ public:
|
||||
: 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)
|
||||
@ -851,6 +868,10 @@ public:
|
||||
: 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)
|
||||
@ -873,6 +894,10 @@ public:
|
||||
: 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)
|
||||
@ -902,6 +927,10 @@ public:
|
||||
: 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)
|
||||
@ -933,6 +962,10 @@ public:
|
||||
: 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)
|
||||
@ -950,28 +983,22 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// Initializes and returns a Vec of length 2.
|
||||
/// 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 <typename T>
|
||||
VTKM_EXEC_CONT vtkm::Vec<T, 2> make_Vec(const T& x, const T& y)
|
||||
template <vtkm::IdComponent Size, typename T>
|
||||
VTKM_EXEC_CONT vtkm::Vec<T, Size> make_Vec(std::initializer_list<T> values)
|
||||
{
|
||||
return vtkm::Vec<T, 2>(x, y);
|
||||
return vtkm::Vec<T, Size>(values);
|
||||
}
|
||||
|
||||
/// Initializes and returns a Vec of length 3.
|
||||
/// 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>
|
||||
VTKM_EXEC_CONT vtkm::Vec<T, 3> make_Vec(const T& x, const T& y, const T& z)
|
||||
template <typename T, typename... Ts>
|
||||
VTKM_EXEC_CONT vtkm::Vec<T, sizeof...(Ts) + 1> make_Vec(const T& value0, const Ts&... values)
|
||||
{
|
||||
return vtkm::Vec<T, 3>(x, y, z);
|
||||
}
|
||||
|
||||
/// Initializes and returns a Vec of length 4.
|
||||
///
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT 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);
|
||||
return vtkm::Vec<T, sizeof...(Ts) + 1>({ value0, values... });
|
||||
}
|
||||
|
||||
/// \brief A Vec-like representation for short arrays.
|
||||
|
@ -453,6 +453,12 @@ void TypeTest(const vtkm::Vec<Scalar, 2>&)
|
||||
Vector b(1, 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.");
|
||||
|
||||
Vector plus = a + b;
|
||||
VTKM_TEST_ASSERT(test_equal(plus, vtkm::make_Vec(3, 6)), "Vectors do not add correctly.");
|
||||
|
||||
@ -514,6 +520,13 @@ void TypeTest(const vtkm::Vec<Scalar, 3>&)
|
||||
Vector b(1, 2, 3);
|
||||
Scalar s = 5;
|
||||
|
||||
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.");
|
||||
|
||||
Vector plus = a + b;
|
||||
VTKM_TEST_ASSERT(test_equal(plus, vtkm::make_Vec(3, 6, 9)), "Vectors do not add correctly.");
|
||||
|
||||
@ -576,6 +589,13 @@ void TypeTest(const vtkm::Vec<Scalar, 4>&)
|
||||
Vector b(1, 2, 3, 4);
|
||||
Scalar s = 5;
|
||||
|
||||
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.");
|
||||
|
||||
Vector plus = a + b;
|
||||
VTKM_TEST_ASSERT(test_equal(plus, vtkm::make_Vec(3, 6, 9, 12)), "Vectors do not add correctly.");
|
||||
|
||||
|
@ -49,7 +49,7 @@ struct ShiftScaleToRGB : public vtkm::worklet::WorkletMapField
|
||||
{ //vtkScalarsToColorsLuminanceToRGB
|
||||
vtkm::Float32 l = (static_cast<vtkm::Float32>(in) + this->Shift) * this->Scale;
|
||||
colorconversion::Clamp(l);
|
||||
return vtkm::Vec<vtkm::UInt8, 3>{ static_cast<vtkm::UInt8>(l + 0.5f) };
|
||||
return vtkm::Vec<vtkm::UInt8, 3>(static_cast<vtkm::UInt8>(l + 0.5f));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
Loading…
Reference in New Issue
Block a user