// // vector_test.cpp // vector // // Created by Sam Jaffe on 6/2/18. // #include #include "math/vector/vector.hpp" template math::vector::vector iota() { math::vector::vector rval; for (size_t i = 0; i < N; ++i) rval[i] = static_cast(i + 1); return rval; } using vec2i = math::vector::vector; using vec3 = math::vector::vector; using vec3i = math::vector::vector; using vec4i = math::vector::vector; vec2i iota2i() { return iota(); } vec3i iota3i() { return iota(); } vec4i iota4i() { return iota(); } TEST(Vector, Equality) { EXPECT_THAT((iota3i()), vec3i({1, 2, 3})); EXPECT_THAT((iota3i()), ::testing::Ne(vec3i({0, 2, 3}))); } TEST(Vector, Comparison) { vec3i const iota = iota3i(); vec3i const low_lt({0, 2, 3}); vec3i const mid_lt({1, 1, 3}); vec3i const high_lt({1, 2, 2}); vec3i const low_gt({2, 2, 3}); vec3i const mid_gt({1, 3, 3}); vec3i const high_gt({1, 2, 4}); EXPECT_THAT(iota, ::testing::Gt(low_lt)); EXPECT_THAT(iota, ::testing::Gt(mid_lt)); EXPECT_THAT(iota, ::testing::Gt(high_lt)); EXPECT_THAT(iota, ::testing::Ge(low_lt)); EXPECT_THAT(iota, ::testing::Ge(iota)); EXPECT_THAT(iota, ::testing::Lt(low_gt)); EXPECT_THAT(iota, ::testing::Lt(mid_gt)); EXPECT_THAT(iota, ::testing::Lt(high_gt)); EXPECT_THAT(iota, ::testing::Le(low_gt)); EXPECT_THAT(iota, ::testing::Le(iota)); } TEST(Vector, DefaultConstructorIsAllZero) { EXPECT_THAT(vec3i(), vec3i({0, 0, 0})); } TEST(Vector, FillConstructorInsertsAllElements) { EXPECT_THAT(vec3i(1, math::vector::fill), vec3i({1, 1, 1})); } TEST(Vector, ExtensionConstructorAppendsZeros) { EXPECT_THAT(vec4i(iota3i()), vec4i({1, 2, 3, 0})); } TEST(Vector, CanAccessVectorElements) { math::vector::vector viota = iota3i(); EXPECT_THAT(viota[0], 1); EXPECT_THAT(viota[1], 2); EXPECT_THAT(viota[2], 3); } TEST(Vector, CanAccessVectorElementsWithNames) { math::vector::vector viota = iota4i(); EXPECT_THAT(viota.x(), 1); EXPECT_THAT(viota.y(), 2); EXPECT_THAT(viota.z(), 3); EXPECT_THAT(viota.w(), 4); } TEST(Vector, CanAccessVectorElementsWithColorNames) { math::vector::vector viota = iota4i(); EXPECT_THAT(viota.r(), 1); EXPECT_THAT(viota.g(), 2); EXPECT_THAT(viota.b(), 3); EXPECT_THAT(viota.a(), 4); } TEST(Vector, AccessingOutOfRangeThrows) { EXPECT_THROW(iota3i().at(3), std::out_of_range); } TEST(Vector, CrossProduct2DHasOnlyZElement) { EXPECT_THAT(vec2i({1, 1}).cross(vec2i({-1, 1})), vec3i({0, 0, 2})); } TEST(Vector, CrossProduct3DHasAllElements) { EXPECT_THAT(vec3i({1, 1, 2}).cross(vec3i({-1, 1, 1})), vec3i({-1, -3, 2})); } TEST(Vector, AdditionIsPiecewise) { EXPECT_THAT((vec2i{{1, 0}} + vec2i{{0, 1}}), vec2i({1, 1})); } TEST(Vector, SubtractionIsPiecewise) { EXPECT_THAT((vec2i{{1, 0}} - vec2i{{0, 1}}), vec2i({1, -1})); } TEST(Vector, MultiplicationIsPiecewise) { EXPECT_THAT((vec2i{{1, 0}} * vec2i({2, 1})), vec2i({2, 0})); } TEST(Vector, DivisionIsPiecewise) { EXPECT_THAT((vec2i{{6, 4}} / vec2i({2, 1})), vec2i({3, 4})); } TEST(Vector, DivisionByZeroThrowsException) { EXPECT_THROW(vec3{} / 0, std::domain_error); EXPECT_THROW((vec3{{1.0, 1.0, 1.0}} / vec3({1.0, 0.5, 0.0})), std::domain_error); } TEST(Vector, AdditionWithValueType) { EXPECT_THAT(vec2i({1, 0}) + 1, vec2i({2, 1})); EXPECT_THAT(1 + iota2i(), vec2i({2, 3})); } TEST(Vector, SubtractionWithValueType) { EXPECT_THAT(4 - iota2i(), vec2i({3, 2})); EXPECT_THAT(vec2i({1, 0}) - 1, vec2i({0, -1})); } TEST(Vector, MultiplicationWithValueType) { EXPECT_THAT((vec2i{{1, 0}} * 3), vec2i({3, 0})); EXPECT_THAT(2 * iota2i(), vec2i({2, 4})); } TEST(Vector, DivisionWithValueType) { EXPECT_THAT((vec2i{{6, 4}} / 2), vec2i({3, 2})); // EXPECT_THAT(4/iota2i(), (vec2i{4,2})); } TEST(Vector, OperatorPlusEqualsMutatesValue) { vec3i vec = iota3i(); EXPECT_THAT(vec += iota3i(), vec3i({2, 4, 6})); EXPECT_THAT(vec, vec3i({2, 4, 6})); EXPECT_THAT(vec += 1, vec3i({3, 5, 7})); EXPECT_THAT(vec, vec3i({3, 5, 7})); } TEST(Vector, OperatorMinusEqualsMutatesValue) { vec3i vec = iota3i(); EXPECT_THAT(vec -= 1, vec3i({0, 1, 2})); EXPECT_THAT(vec, vec3i({0, 1, 2})); EXPECT_THAT(vec -= iota3i(), vec3i({-1, -1, -1})); EXPECT_THAT(vec, vec3i({-1, -1, -1})); } TEST(Vector, MultiplicationWorksAcrossTypes) { EXPECT_THAT(iota3i() * 0.5, vec3({0.5, 1.0, 1.5})); EXPECT_THAT(0.5 * iota3i(), vec3({0.5, 1.0, 1.5})); EXPECT_THAT(vec3({2.0, 1.5, -2}) * iota3i(), vec3({2.0, 3.0, -6.0})); } TEST(Vector, DivisionWorksAcrossTypes) { EXPECT_THAT(iota3i() / 0.5, vec3({2.0, 4.0, 6.0})); EXPECT_THAT(iota3i() / vec3({2.0, 2.5, -2}), vec3({0.5, 0.8, -1.5})); EXPECT_THAT(vec3({2.0, 2.5, -3}) / iota3i(), vec3({2.0, 1.25, -1.0})); } TEST(Vector, Length) { // EXPECT_THAT(iota3i().lengthSquared(), 14); EXPECT_THAT(iota3i().magnitude(), ::testing::DoubleNear(std::sqrt(14), std::numeric_limits::epsilon())); } TEST(Vector, Distance) { // EXPECT_THAT((iota3i().distanceSquared(vec3i{3, 1, -1})), 21); EXPECT_THAT((iota3i() - vec3i({3, 1, -1})).magnitude(), ::testing::DoubleNear(std::sqrt(21), std::numeric_limits::epsilon())); } TEST(Vector, Projection) { EXPECT_THAT(iota3i().projection(vec3i({3, 1, -1})).magnitude(), ::testing::DoubleNear(std::sqrt(4.0 / 11.0), std::numeric_limits::epsilon())); } TEST(Vector, DotProductIsSumOfElementProducts) { EXPECT_THAT(iota3i().dot(vec3i({3, 0, -1})), 0); } TEST(Vector, UnitFunctionCreatesNewVectorOverMagnitude) { double sq = std::sqrt(14); auto unit = iota3i().unit(); EXPECT_THAT(unit[0], ::testing::DoubleNear( 1 / sq, std::numeric_limits::epsilon())); EXPECT_THAT(unit[1], ::testing::DoubleNear( 2 / sq, std::numeric_limits::epsilon())); EXPECT_THAT(unit[2], ::testing::DoubleNear( 3 / sq, std::numeric_limits::epsilon())); } TEST(Vector, CanCastEntireVectorThroughConstructor) { EXPECT_THAT(vec3i(vec3({1.0, 2.3, 3.9})), iota3i()); } TEST(Vector, SwapExchangesAllValues) { using std::swap; vec2i a{{1, 2}}; const vec2i ac = a; vec2i b{{5, 7}}; const vec2i bc = b; swap(a, b); EXPECT_THAT(a, bc); EXPECT_THAT(b, ac); } TEST(Vector, UnaryNegateOperatorNegatesAllElements) { EXPECT_THAT(-iota3i(), vec3i({-1, -2, -3})); } TEST(Vector, AbsoluteValueOfVectorAbsAllElements) { EXPECT_THAT(iota3i(), abs(-iota3i())); } TEST(Vector, MakeVectorAllowsConstuctionFromVariadicComponents) { EXPECT_TRUE((std::is_same::value)); EXPECT_THAT(iota2i(), make_vector(1, 2)); EXPECT_FALSE((std::is_same::value)); EXPECT_TRUE((std::is_same::value)); EXPECT_THAT(iota3i(), make_vector(1, 2, 3)); }