Enable Vec construction with intializer_list of single value

Previously, the initilaizer_list of Vec had to be the exact
same number of values as the size of the Vec. Now, we also
accept a single value that is duplicated for all values in
the Vec. That allows you to more easily construct lists
of lists with repeated values.
This commit is contained in:
Kenneth Moreland 2018-06-04 11:32:18 -05:00
parent 79afe2a169
commit 1578944360
4 changed files with 108 additions and 30 deletions

@ -17,7 +17,13 @@ vtkm::Vec<vtkm::Float64, 3> vec3(1.1, 2.2, 3.3); // Old style that still works b
// probably should be deprecated.
```
The nice thing about the initializer list implementation is that it works for any
Nested initializer lists work to initialize `Vec`s of `Vec`s.
``` cpp
vtkm::Vec<vtkm::Vec<vtkm::Float64, 2>, 3> vec{ {1.1, 2.2}, {3.3, 4.4}, {5.5, 6.6} };
```
The nice thing about the `std::initializer_list` implementation is that it works for any
size `Vec`. That keeps us from jumping through hoops for larger `Vec`s.
``` cpp
@ -27,6 +33,23 @@ vtkm::Vec<vtkm::Float64, 5> vec2(1.1, 2.2, 3.3, 4.4, 5.5); // ERROR! This constr
// not implemented!
```
If a `vtkm::Vec` is initialized with a list of size one, then that one value is
replicated for all components.
``` cpp
vtkm::Vec<vtkm::Float64, 3> vec{1.1}; // vec gets [ 1.1, 1.1, 1.1 ]
```
This "scalar" initialization also works for `Vec`s of `Vec`s.
``` cpp
vtkm::Vec<vtkm::Vec<vtkm::Float64, 2>, 3> vec1{ { 1.1, 2.2 } };
// vec1 is [[1.1, 2.2], [1.1, 2.2], [1.1, 2.2]]
vtkm::Vec<vtkm::Vec<vtkm::Float64, 2>, 3> vec2{ { 3.3}, { 4.4 }, { 5.5 } };
// vec2 is [[3.3, 3.3], [4.4, 4.4], [5.5, 5.5]]
```
`vtkm::make_Vec` is also updated to support an arbitrary number initial values.
``` cpp
@ -40,7 +63,7 @@ This is super convenient when dealing with variadic function arguments.
template <typename... Ts>
void ExampleVariadicFunction(const Ts&... params)
{
auto vec = vtkm::make_Vec(params);
auto vec = vtkm::make_Vec(params...);
```
Of course, this assumes that the type of all the parameters is the same. If not, you
@ -69,18 +92,3 @@ correct for that. (Of course, asserts are not compiled in release builds.)
// 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};
```

@ -628,13 +628,25 @@ 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)
auto src = values.begin();
if (values.size() == 1)
{
*dest = *src;
++dest;
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;
}
}
}

@ -449,8 +449,8 @@ void TypeTest(const vtkm::Vec<Scalar, 2>&)
GeneralVecTypeTest(Vector());
Vector a(2, 4);
Vector b(1, 2);
Vector a{ 2, 4 };
Vector b = { 1, 2 };
Scalar s = 5;
VTKM_TEST_ASSERT(a == vtkm::make_Vec(Scalar(2), Scalar(4)), "make_Vec creates different object.");
@ -516,8 +516,8 @@ void TypeTest(const vtkm::Vec<Scalar, 3>&)
GeneralVecTypeTest(Vector());
Vector a(2, 4, 6);
Vector b(1, 2, 3);
Vector a = { 2, 4, 6 };
Vector b{ 1, 2, 3 };
Scalar s = 5;
VTKM_TEST_ASSERT(a == vtkm::make_Vec(Scalar(2), Scalar(4), Scalar(6)),
@ -585,8 +585,8 @@ void TypeTest(const vtkm::Vec<Scalar, 4>&)
GeneralVecTypeTest(Vector());
Vector a(2, 4, 6, 8);
Vector b(1, 2, 3, 4);
Vector a{ 2, 4, 6, 8 };
Vector b = { 1, 2, 3, 4 };
Scalar s = 5;
VTKM_TEST_ASSERT(a == vtkm::make_Vec(Scalar(2), Scalar(4), Scalar(6), Scalar(8)),
@ -705,6 +705,62 @@ void TypeTest(Scalar)
}
}
template <typename Scalar>
void TypeTest(vtkm::Vec<vtkm::Vec<Scalar, 2>, 3>)
{
using Vector = vtkm::Vec<vtkm::Vec<Scalar, 2>, 3>;
{
Vector vec = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
std::cout << "Initialize completely " << vec << std::endl;
VTKM_TEST_ASSERT(test_equal(vec[0][0], 0), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[0][1], 1), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[1][0], 2), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[1][1], 3), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[2][0], 4), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[2][1], 5), "Vec of vec initializer list wrong.");
}
{
Vector vec = { vtkm::make_Vec(Scalar(0), Scalar(1)) };
std::cout << "Initialize inner " << vec << std::endl;
VTKM_TEST_ASSERT(test_equal(vec[0][0], 0), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[0][1], 1), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[1][0], 0), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[1][1], 1), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[2][0], 0), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[2][1], 1), "Vec of vec initializer list wrong.");
}
{
Vector vec = { { 0, 1 } };
std::cout << "Initialize inner " << vec << std::endl;
VTKM_TEST_ASSERT(test_equal(vec[0][0], 0), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[0][1], 1), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[1][0], 0), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[1][1], 1), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[2][0], 0), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[2][1], 1), "Vec of vec initializer list wrong.");
}
{
Vector vec = { { 0 }, { 1 }, { 2 } };
std::cout << "Initialize outer " << vec << std::endl;
VTKM_TEST_ASSERT(test_equal(vec[0][0], 0), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[0][1], 0), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[1][0], 1), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[1][1], 1), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[2][0], 2), "Vec of vec initializer list wrong.");
VTKM_TEST_ASSERT(test_equal(vec[2][1], 2), "Vec of vec initializer list wrong.");
}
{
// Both of these constructors are disallowed.
//Vector vec1 = { 0, 1, 2 };
//Vector vec2 = { 0, 1 };
}
}
struct TypeTestFunctor
{
template <typename T>
@ -719,7 +775,9 @@ 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::Float64, 1>>>
vtkm::Vec<vtkm::Float64, 1>,
vtkm::Vec<vtkm::Id2, 3>,
vtkm::Vec<vtkm::Vec<vtkm::Float32, 2>, 3>>>
{
};

@ -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>