Add vector_cast implementation and the unit test for it.

This commit is contained in:
King_DuckZ 2016-11-02 01:15:10 +01:00
parent dc1b3e7b76
commit 891fa25675
5 changed files with 178 additions and 0 deletions

View file

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

View 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

View 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}
)

View 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

View 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());
}
}