| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- //
- // vector_test.cpp
- // vector
- //
- // Created by Sam Jaffe on 6/2/18.
- //
- #include <testing/xcode_gtest_helper.h>
- #include "math/vector/vector.hpp"
- template <typename T, size_t N> math::vector::vector<T, N> iota() {
- math::vector::vector<T, N> rval;
- for (size_t i = 0; i < N; ++i)
- rval[i] = static_cast<T>(i + 1);
- return rval;
- }
- using math::vector::vector;
- using vec2i = math::vector::vector<int, 2>;
- using vec3 = math::vector::vector<double, 3>;
- using vec3i = math::vector::vector<int, 3>;
- using vec4i = math::vector::vector<int, 4>;
- vec2i iota2i() { return iota<int, 2>(); }
- vec3i iota3i() { return iota<int, 3>(); }
- vec4i iota4i() { return iota<int, 4>(); }
- 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<int, 3> viota = iota3i();
- EXPECT_THAT(viota[0], 1);
- EXPECT_THAT(viota[1], 2);
- EXPECT_THAT(viota[2], 3);
- }
- TEST(Vector, CanAccessVectorElementsWithNames) {
- math::vector::vector<int, 4> 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<int, 4> 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<double>::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<double>::epsilon()));
- }
- TEST(Vector, Projection) {
- EXPECT_THAT(iota3i().projection(vec3i{3, 1, -1}).magnitude(),
- ::testing::DoubleNear(std::sqrt(4.0 / 11.0),
- std::numeric_limits<double>::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<double>::epsilon()));
- EXPECT_THAT(unit[1], ::testing::DoubleNear(
- 2 / sq, std::numeric_limits<double>::epsilon()));
- EXPECT_THAT(unit[2], ::testing::DoubleNear(
- 3 / sq, std::numeric_limits<double>::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, CanPerformTypeDeduced) {
- EXPECT_TRUE((std::is_same<vec2i, decltype(vector{1, 2})>::value));
- EXPECT_THAT(iota2i(), vector(1, 2));
- EXPECT_FALSE((std::is_same<vec2i, decltype(vector{1, 2, 3})>::value));
- EXPECT_TRUE((std::is_same<vec3i, decltype(vector{1, 2, 3})>::value));
- EXPECT_THAT(iota3i(), vector(1, 2, 3));
- }
|