From 15789443601c565f70e8e6b8de349d87eb1dcfbd Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Mon, 4 Jun 2018 11:32:18 -0500 Subject: [PATCH] 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. --- docs/changelog/vec-initializer-lists.md | 42 ++++++----- vtkm/Types.h | 22 ++++-- vtkm/testing/UnitTestTypes.cxx | 72 +++++++++++++++++-- .../worklet/colorconversion/ShiftScaleToRGB.h | 2 +- 4 files changed, 108 insertions(+), 30 deletions(-) diff --git a/docs/changelog/vec-initializer-lists.md b/docs/changelog/vec-initializer-lists.md index b27e2b328..0d28c6e22 100644 --- a/docs/changelog/vec-initializer-lists.md +++ b/docs/changelog/vec-initializer-lists.md @@ -17,7 +17,13 @@ vtkm::Vec 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, 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 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 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, 3> vec1{ { 1.1, 2.2 } }; +// vec1 is [[1.1, 2.2], [1.1, 2.2], [1.1, 2.2]] + +vtkm::Vec, 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 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 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 vec1(3.14); - -// The result of this is underfined. In debug builds, it will fail an assert. -vtkm::Vec vec1{3.14}; -``` diff --git a/vtkm/Types.h b/vtkm/Types.h index 9912f2b7e..7a13a51fa 100644 --- a/vtkm/Types.h +++ b/vtkm/Types.h @@ -628,13 +628,25 @@ protected: VTKM_EXEC_CONT VecBase(std::initializer_list 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; + } } } diff --git a/vtkm/testing/UnitTestTypes.cxx b/vtkm/testing/UnitTestTypes.cxx index b09b449c1..aa4ebbe12 100644 --- a/vtkm/testing/UnitTestTypes.cxx +++ b/vtkm/testing/UnitTestTypes.cxx @@ -449,8 +449,8 @@ void TypeTest(const vtkm::Vec&) 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&) 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&) 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 +void TypeTest(vtkm::Vec, 3>) +{ + using Vector = vtkm::Vec, 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 @@ -719,7 +775,9 @@ struct TypesToTest : vtkm::ListTagJoin, vtkm::Vec, vtkm::Vec, - vtkm::Vec>> + vtkm::Vec, + vtkm::Vec, + vtkm::Vec, 3>>> { }; diff --git a/vtkm/worklet/colorconversion/ShiftScaleToRGB.h b/vtkm/worklet/colorconversion/ShiftScaleToRGB.h index a57c7d61b..e7679f2e8 100644 --- a/vtkm/worklet/colorconversion/ShiftScaleToRGB.h +++ b/vtkm/worklet/colorconversion/ShiftScaleToRGB.h @@ -49,7 +49,7 @@ struct ShiftScaleToRGB : public vtkm::worklet::WorkletMapField { //vtkScalarsToColorsLuminanceToRGB vtkm::Float32 l = (static_cast(in) + this->Shift) * this->Scale; colorconversion::Clamp(l); - return vtkm::Vec(static_cast(l + 0.5f)); + return vtkm::Vec{ static_cast(l + 0.5f) }; } template