Add vector_cast implementation and the unit test for it.
This commit is contained in:
parent
dc1b3e7b76
commit
891fa25675
5 changed files with 178 additions and 0 deletions
|
@ -34,6 +34,9 @@ You still need to type some code in order to get started using the vector wrappe
|
|||
### Automated conversion ###
|
||||
You can assign or construct a `Vec<A>` from a `Vec<B>`, provided they have the same dimensions and the assignemnt operator is able to convert B's scalar type to that of A. You need to define VWR_WITH_IMPLICIT_CONVERSIONS for this to work.
|
||||
|
||||
### Manual conversions ###
|
||||
You can convert one vector to the other using vector_cast. For example, auto b = vector_cast<float2>(a); will create a temporary of type float2 the whose elements are a static_cast'ed copy of the elements in a and assign it to b. You need to include vectorwrapper/vector_cast.hpp.
|
||||
|
||||
### Access the wrapped type ###
|
||||
Through the `data()` method you can always obtain a ref to the wrapped type.
|
||||
|
||||
|
|
44
include/vectorwrapper/vector_cast.hpp
Normal file
44
include/vectorwrapper/vector_cast.hpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Michele "King_DuckZ" Santullo
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef idE24EF7737A7F4882B2BF254F0A3EEC34
|
||||
#define idE24EF7737A7F4882B2BF254F0A3EEC34
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace vwr {
|
||||
namespace implem {
|
||||
template <typename TO, typename FROM, std::size_t... I>
|
||||
Vec<TO> vector_cast (const Vec<FROM>& parVec, Vec<TO>*, std::index_sequence<I...>) {
|
||||
static_assert(
|
||||
static_cast<int>(Vec<TO>::dimensions) == static_cast<int>(Vec<FROM>::dimensions),
|
||||
"Mismatching dimensions"
|
||||
);
|
||||
static_assert(sizeof...(I) == Vec<TO>::dimensions, "Mismatching index count");
|
||||
typedef typename Vec<TO>::scalar_type CastType;
|
||||
|
||||
return Vec<TO>(static_cast<CastType>(parVec[I])...);
|
||||
}
|
||||
} //namespace implem
|
||||
|
||||
template <typename TOVec, typename FROM>
|
||||
TOVec vector_cast (const Vec<FROM>& parVec) {
|
||||
TOVec* const to = nullptr;
|
||||
return implem::vector_cast(parVec, to, std::make_index_sequence<Vec<FROM>::dimensions>());
|
||||
}
|
||||
} //namespace vwr
|
||||
|
||||
#endif
|
28
test/unit_noconv/CMakeLists.txt
Normal file
28
test/unit_noconv/CMakeLists.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
project(unit_noconv CXX)
|
||||
|
||||
set(warning_flags "-Wall -Wextra -Wconversion -Werror")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${warning_flags}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${warning_flags}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${warning_flags}")
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
${GTEST_MAIN_CPP}
|
||||
test_conversions.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
gtest
|
||||
)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE VWR_STATIC_CAST_RESULTS
|
||||
)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD_REQUIRED ON)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 14)
|
||||
|
||||
add_test(
|
||||
NAME TestNoImplicitConversion
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMAND ${PROJECT_NAME}
|
||||
)
|
32
test/unit_noconv/sample_vector.hpp
Normal file
32
test/unit_noconv/sample_vector.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef idD52B2591EB8240A980C5B3823D025EC1
|
||||
#define idD52B2591EB8240A980C5B3823D025EC1
|
||||
|
||||
#include "vectorwrapper/vectorwrapper.hpp"
|
||||
#include <array>
|
||||
|
||||
#define SPECIALIZE_ARRAY_VECTOR(TYPE, DIM) \
|
||||
template <> \
|
||||
struct VectorWrapperInfo<std::array<TYPE, DIM>> { \
|
||||
enum { dimensions = DIM }; \
|
||||
typedef TYPE scalar_type; \
|
||||
typedef std::array<scalar_type, dimensions> vector_type; \
|
||||
static scalar_type& get_at (size_t parIndex, vector_type& parVector) { \
|
||||
return parVector[parIndex]; \
|
||||
} \
|
||||
}
|
||||
|
||||
namespace vwr {
|
||||
SPECIALIZE_ARRAY_VECTOR(float, 2);
|
||||
SPECIALIZE_ARRAY_VECTOR(float, 3);
|
||||
SPECIALIZE_ARRAY_VECTOR(short int, 2);
|
||||
SPECIALIZE_ARRAY_VECTOR(short int, 3);
|
||||
|
||||
typedef Vec<std::array<float, 2>> float2;
|
||||
typedef Vec<std::array<float, 3>> float3;
|
||||
typedef Vec<std::array<short int, 2>> short2;
|
||||
typedef Vec<std::array<short int, 3>> short3;
|
||||
} //namespace vwr
|
||||
|
||||
#undef SPECIALIZE_ARRAY_VECTOR
|
||||
|
||||
#endif
|
71
test/unit_noconv/test_conversions.cpp
Normal file
71
test/unit_noconv/test_conversions.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include "sample_vector.hpp"
|
||||
#include "vectorwrapper/vector_cast.hpp"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(vwr, vector_cast) {
|
||||
using namespace vwr;
|
||||
|
||||
{
|
||||
float2 v1(1.0f, 2.0f);
|
||||
short2 v2(vector_cast<short2>(v1));
|
||||
|
||||
EXPECT_EQ(1, v2.x());
|
||||
EXPECT_EQ(2, v2.y());
|
||||
}
|
||||
|
||||
{
|
||||
short3 v1(3, 4, 5);
|
||||
auto v2 = vector_cast<float3>(v1) / float3(2.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(1.5f, v2.x());
|
||||
EXPECT_FLOAT_EQ(2.0f, v2.y());
|
||||
EXPECT_FLOAT_EQ(2.5f, v2.z());
|
||||
}
|
||||
|
||||
{
|
||||
short3 v1(0xAB, 0xCD, 0xEF);
|
||||
short3 v2(0x12, 0x34, 0x56);
|
||||
float3 v3(vector_cast<float3>(v1 + v2));
|
||||
|
||||
EXPECT_FLOAT_EQ(static_cast<float>(0xAB + 0x12), v3.x());
|
||||
EXPECT_FLOAT_EQ(static_cast<float>(0xCD + 0x34), v3.y());
|
||||
EXPECT_FLOAT_EQ(static_cast<float>(0xEF + 0x56), v3.z());
|
||||
|
||||
short3 v4 = vector_cast<short3>(v3);
|
||||
EXPECT_EQ(0xAB + 0x12, v4.x());
|
||||
EXPECT_EQ(0xCD + 0x34, v4.y());
|
||||
EXPECT_EQ(0xEF + 0x56, v4.z());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(vwr, promotion_static_cast) {
|
||||
using namespace vwr;
|
||||
|
||||
{
|
||||
short2 v1(100, 200);
|
||||
auto v2 = v1 / short2(2);
|
||||
EXPECT_EQ(50, v2.x());
|
||||
EXPECT_EQ(100, v2.y());
|
||||
}
|
||||
|
||||
{
|
||||
short2 v1(100, 200);
|
||||
auto v2 = v1 * short2(2);
|
||||
EXPECT_EQ(200, v2.x());
|
||||
EXPECT_EQ(400, v2.y());
|
||||
}
|
||||
|
||||
{
|
||||
short2 v1(100, 200);
|
||||
auto v2 = v1 + short2(2);
|
||||
EXPECT_EQ(102, v2.x());
|
||||
EXPECT_EQ(202, v2.y());
|
||||
}
|
||||
|
||||
{
|
||||
short2 v1(100, 200);
|
||||
auto v2 = v1 - short2(2);
|
||||
EXPECT_EQ(98, v2.x());
|
||||
EXPECT_EQ(198, v2.y());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue