Commits

Anonymous committed ee16511

Tons of more vector fixes.

Comments (0)

Files changed (7)

neglect/cpplib/include/neglect/_vector2.hpp

             struct { T s, t; };
         };
 
+        typedef T value_type;
+
         // -- constructors
 
         vector() : x(T()), y(T())
             return *(&x + idx);
         }
 
-        // -- comparison operators
-
-        bool operator==(const vector<T, 2> &other) const
-        {
-            return x == other.x && y == other.y;
-        }
-
-        bool operator!=(const vector<T, 2> &other) const
-        {
-            return x != other.x || y != other.y;
-        }
-
         // -- arithmetic operators
 
         vector<T, 2> operator+(const vector<T, 2> &other) const

neglect/cpplib/include/neglect/_vector3.hpp

             struct { T s, t, p; };
         };
 
+        typedef T value_type;
+
         // -- constructors
 
         vector() : x(T()), y(T()), z(T())
             return *(&x + idx);
         }
 
-        // -- comparison operators
-
-        bool operator==(const vector<T, 3> &other) const
-        {
-            return x == other.x && y == other.y && z == other.z;
-        }
-
-        bool operator!=(const vector<T, 3> &other) const
-        {
-            return x != other.x || y != other.y || z != other.z;
-        }
-
         // -- arithmetic operators
 
         vector<T, 3> operator+(const vector<T, 3> &other) const
         vector<T, 3> operator/(ScalarType scalar) const
         {
             assert(scalar);
-            ScalarType inv = static_cast<ScalarType>(1) / scalar;
-            return vector<T, 3>(x * inv, y * inv, z * inv);
+            return vector<T, 3>(x / scalar, y / scalar, z / scalar);
         }
 
         const vector<T, 3> &operator+() const
             x += other.x;
             y += other.y;
             z += other.z;
+            return *this;
         }
 
         vector<T, 3> &operator-=(const vector<T, 3> &other)
             x -= other.x;
             y -= other.y;
             z -= other.z;
+            return *this;
         }
 
         vector<T, 3> &operator*=(const vector<T, 3> &other)
         {
             x *= other.x;
             y *= other.y;
-            y *= other.z;
+            z *= other.z;
+            return *this;
         }
 
         template <class ScalarType>
         vector<T, 3> &operator*=(ScalarType scalar)
         {
-            x *= other;
-            y *= other;
-            z *= other;
+            x *= scalar;
+            y *= scalar;
+            z *= scalar;
+            return *this;
         }
 
         vector<T, 3> &operator/=(const vector<T, 3> &other)
             x /= other.x;
             y /= other.y;
             z /= other.z;
+            return *this;
         }
 
         template <class ScalarType>
         vector<T, 3> &operator/=(ScalarType scalar)
         {
             assert(scalar);
-            ScalarType inv = static_cast<ScalarType>(1) / scalar;
-            x *= inv;
-            y *= inv;
-            z *= inv;
+            x /= scalar;
+            y /= scalar;
+            z /= scalar;
+            return *this;
         }
 
         // -- helper methods

neglect/cpplib/include/neglect/_vector4.hpp

             struct { T s, t, p, q; };
         };
 
+        typedef T value_type;
+
         // -- constructors
 
         vector() : x(T()), y(T()), z(T()), w(T())
             return *(&x + idx);
         }
 
-        // -- comparison operators
-
-        bool operator==(const vector<T, 4> &other) const
-        {
-            return x == other.x && y == other.y && z == other.z
-                && w == other.w;
-        }
-
-        bool operator!=(const vector<T, 4> &other) const
-        {
-            return x != other.x || y != other.y || z != other.z
-                || w != other.w;
-        }
-
         // -- arithmetic operators
 
         vector<T, 4> operator+(const vector<T, 4> &other) const

neglect/cpplib/include/neglect/unittest.hpp

         int successful_tests() const { return m_test_count - m_failed_tests; }
         int test_count() const { return m_test_count; }
         int error_count() const { return m_errors.size(); }
+        bool has_errors() const { return !m_errors.empty(); }
 
         typedef std::vector<test_error>::const_iterator error_iterator;
         error_iterator errors_begin() const { return m_errors.begin(); }
         }
 
         template <class A, class B>
+        bool check_not_equal(A a, B b, const location &loc)
+        {
+            if (a != b)
+                return true;
+
+            std::stringstream details;
+            details << "expression: " << a << " != " << b;
+
+            test_error err;
+            err.loc = loc;
+            err.type = "Inequality check failed";
+            err.message = "the two objects are equal";
+            err.details = details.str();
+            record_test_error(err);
+            return false;
+        }
+
+        template <class A, class B>
         bool check_almost_equal(A a, B b, const location &loc)
         {
             if (almost_equal(a, b))
             }
         }
 
-        void require(bool expr, const std::string &expr_repr, const location &loc)
-        {
-            if (!check(expr, expr_repr, loc))
-                throw abort_test();
-        }
-
-        template <class A, class B>
-        void require_equal(A a, B b, const location &loc)
-        {
-            if (!check_equal(a, b, loc))
-                throw abort_test();
-        }
-
-        template <class A, class B>
-        void require_almost_equal(A a, B b, const location &loc)
-        {
-            if (!check_almost_equal(a, b, loc))
-                throw abort_test();
-        }
-
     private:
         std::ostream &m_stream;
         std::vector<test_error> m_errors;
 
 /* test helpers */
 #define _NUT_LOCATION ::neglect::unittest::location(__FILE__, __LINE__, this)
-#define NUT_REQUIRE(expr) runner.require(expr, #expr, _NUT_LOCATION)
-#define NUT_REQUIRE_EQUAL(a, b) runner.require_equal(a, b, _NUT_LOCATION)
-#define NUT_REQUIRE_ALMOST_EQUAL(a, b) runner.require_almost_equal(a, b, _NUT_LOCATION)
+#define _NUT_ABORTIF(expr) \
+    do { if (expr) throw ::neglect::unittest::abort_test(); } while (0)
+
 #define NUT_CHECK(expr) runner.check(expr, #expr, _NUT_LOCATION)
 #define NUT_CHECK_EQUAL(a, b) runner.check_equal(a, b, _NUT_LOCATION)
-#define NUT_CHECK_ALMOST_EQUAL(a, b) runner.check_almost_equal(a, b, _NUT_LOCATION)
+#define NUT_CHECK_NOT_EQUAL(a, b) runner.check_not_equal(a, b, _NUT_LOCATION)
+#define NUT_CHECK_ALMOST_EQUAL(a, b) runner.check_almost_equal(a, b, _NUT_LOCATION)
+#define NUT_REQUIRE(expr) _NUT_ABORTIF(!NUT_CHECK(expr))
+#define NUT_REQUIRE_EQUAL(a, b) _NUT_ABORTIF(!NUT_CHECK_EQUAL(a, b))
+#define NUT_REQUIRE_NOT_EQUAL(a, b) _NUT_ABORTIF(!NUT_CHECK_NOT_EQUAL(a, b))
+#define NUT_REQUIRE_ALMOST_EQUAL(a, b) _NUT_ABORTIF(!NUT_CHECK_ALMOST_EQUAL(a, b))

neglect/cpplib/include/neglect/vector.hpp

     typedef vector<int, 4> veci4;
 
     /* checks if two vectors are amost equal */
-    template <typename T, size_t Size>
-    bool almost_equal(const vector<T, Size> &lhs,
-                      const vector<T, Size> &rhs)
+    template <typename TA, size_t SizeA,
+              typename TB, size_t SizeB>
+    bool operator==(const vector<TA, SizeA> &lhs,
+                    const vector<TB, SizeB> &rhs)
     {
-        for (size_t i = 0; i < Size; i++)
+        if (SizeA != SizeB)
+            return false;
+        for (size_t i = 0; i < SizeA; i++)
+            if (lhs[i] != rhs[i])
+                return false;
+        return true;
+    }
+
+    template <typename TA, size_t SizeA,
+              typename TB, size_t SizeB>
+    bool operator!=(const vector<TA, SizeA> &lhs,
+                    const vector<TB, SizeB> &rhs)
+    {
+        return !(lhs == rhs);
+    }
+
+    template <typename TA, size_t SizeA,
+              typename TB, size_t SizeB>
+    bool almost_equal(const vector<TA, SizeA> &lhs,
+                      const vector<TB, SizeB> &rhs)
+    {
+        if (SizeA != SizeB)
+            return false;
+        for (size_t i = 0; i < SizeA; i++)
             if (!almost_equal(lhs[i], rhs[i]))
                 return false;
         return true;

neglect/tests/src/main.cpp

     getc(stdin);
 #endif
 
-    return 0;
+    return runner.has_errors();
 }

neglect/tests/src/test_vectors.cpp

 #include <neglect/vector.hpp>
 #include <neglect/vector_io.hpp>
 
+#include <boost/type_traits.hpp>
+
 #include <sstream>
 
 
+#define HAS_EXPECTED_TYPE(the_type, expected) \
+    boost::is_same<the_type::value_type, expected>::value
+#define HAS_EXPECTED_SIZE(the_type, expected) \
+    (the_type().size() == expected)
+
+
 using namespace neglect;
 
+NUT_TESTGROUP(vector_typedefs) {
+
+    NUT_TESTCASE(type_checks)
+    {
+        NUT_CHECK(HAS_EXPECTED_TYPE(vec2, float));
+        NUT_CHECK(HAS_EXPECTED_TYPE(vec3, float));
+        NUT_CHECK(HAS_EXPECTED_TYPE(vec4, float));
+        NUT_CHECK(HAS_EXPECTED_TYPE(veci2, int));
+        NUT_CHECK(HAS_EXPECTED_TYPE(veci3, int));
+        NUT_CHECK(HAS_EXPECTED_TYPE(veci4, int));
+    }
+
+    NUT_TESTCASE(size_checks)
+    {
+        NUT_CHECK(HAS_EXPECTED_SIZE(vec2, 2));
+        NUT_CHECK(HAS_EXPECTED_SIZE(vec3, 3));
+        NUT_CHECK(HAS_EXPECTED_SIZE(vec4, 4));
+        NUT_CHECK(HAS_EXPECTED_SIZE(veci2, 2));
+        NUT_CHECK(HAS_EXPECTED_SIZE(veci3, 3));
+        NUT_CHECK(HAS_EXPECTED_SIZE(veci4, 4));
+    }
+}
+
+
 NUT_TESTGROUP(vector2) {
 
     NUT_TESTCASE(constructors)
 
         NUT_CHECK_EQUAL(-v1, vec2(-1.5f, 2.5f));
         NUT_CHECK_EQUAL(v1.norm(), 8.5f);
-        NUT_CHECK_EQUAL(v1.length(), 2.9154759f);
+        NUT_CHECK_ALMOST_EQUAL(v1.length(), 2.9154759f);
         NUT_CHECK(&v1 == &+v1);
     }
 
         vec2 v2(1.0f, 1.0f);
         vec2 v3(5.0f, 3.0f);
         NUT_CHECK_EQUAL(normalize(v1), vec2(1.0f, 0.0f));
-        NUT_CHECK_ALMOST_EQUAL(normalize(v2), vec2(0.70710678f, 0.70710678f));
+        NUT_CHECK_ALMOST_EQUAL(normalize(v2), vec2(0.70710678f,
+                                                   0.70710678f));
         NUT_CHECK_EQUAL(cross(v1, v2), 1.5f);
         NUT_CHECK_EQUAL(dot(v2, v3), 8.0f);
         NUT_CHECK_EQUAL(perpendicular(v3), vec2(-3.0f, 5.0f));
         NUT_CHECK_EQUAL(v1.p, 2.0f);
         NUT_CHECK_EQUAL(v1.b, 2.0f);
     }
+
+    NUT_TESTCASE(basic_math)
+    {
+        vec3 v1(1.5f, -2.5f, 1.0f);
+        vec3 v2(1.0f, 2.0f, 2.0f);
+        vec3 v;
+
+        NUT_CHECK_EQUAL(v1 + v2, vec3(2.5f, -0.5f, 3.0f));
+        v = v1;
+        v += v2;
+        NUT_CHECK_EQUAL(v, vec3(2.5f, -0.5f, 3.0f));
+
+        NUT_CHECK_EQUAL(v1 - v2, vec3(0.5f, -4.5f, -1.0f));
+        v = v1;
+        v -= v2;
+        NUT_CHECK_EQUAL(v, vec3(0.5f, -4.5f, -1.0f));
+
+        NUT_CHECK_EQUAL(v1 * v2, vec3(1.5f, -5.0f, 2.0f));
+        v = v1;
+        v *= v2;
+        NUT_CHECK_EQUAL(v, vec3(1.5f, -5.0f, 2.0f));
+
+        NUT_CHECK_EQUAL(v1 / v2, vec3(1.5f, -1.25f, 0.5f));
+        v = v1;
+        v /= v2;
+        NUT_CHECK_EQUAL(v, vec3(1.5f, -1.25f, 0.5f));
+
+        NUT_CHECK_EQUAL(v2 / 2, vec3(0.5f, 1.0f, 1.0f));
+        v = v2;
+        v /= 2;
+        NUT_CHECK_EQUAL(v, vec3(0.5f, 1.0f, 1.0f));
+
+        NUT_CHECK_EQUAL(v1 * 2, vec3(3.0f, -5.0f, 2.0f));
+        NUT_CHECK_EQUAL(2 * v1, vec3(3.0f, -5.0f, 2.0f));
+        v = v1;
+        v *= 2;
+        NUT_CHECK_EQUAL(v, vec3(3.0f, -5.0f, 2.0f));
+
+        NUT_CHECK_EQUAL(-v1, vec3(-1.5f, 2.5f, -1.0f));
+        NUT_CHECK_EQUAL(v1.norm(), 9.5f);
+        NUT_CHECK_ALMOST_EQUAL(v1.length(), 3.082206964f);
+        NUT_CHECK(&v1 == &+v1);
+    }
+
+    NUT_TESTCASE(vector_functions)
+    {
+        vec3 v1(1.5f, 0.0f, 0.0f);
+        vec3 v2(1.0f, 1.0f, 1.0f);
+        vec3 v3(5.0f, 3.0f, 2.0f);
+        NUT_CHECK_EQUAL(normalize(v1), vec3(1.0f, 0.0f, 0.0f));
+        NUT_CHECK_ALMOST_EQUAL(normalize(v2), vec3(0.577350269f,
+                                                   0.577350269f,
+                                                   0.577350269f));
+        NUT_CHECK_EQUAL(cross(v1, v2), vec3(0.0f, -1.5f, 1.5f));
+        NUT_CHECK_EQUAL(dot(v2, v3), 10.0f);
+        NUT_CHECK_EQUAL(reflect(v3, v2), vec3(-15.0f, -17.0f, -18.0f));
+        NUT_CHECK_ALMOST_EQUAL(distance(v2, v3), 4.582575798f);
+        NUT_CHECK_ALMOST_EQUAL(square_distance(v2, v3), 21.0f);
+    }
+
+    NUT_TESTCASE(stream_support)
+    {
+        std::stringstream ss;
+        vector<float, 3> v1;
+        vector<float, 3> v2(1.0f, 2.5f, 1.5f);
+
+        ss << v1 << " " << v2;
+
+        NUT_CHECK_EQUAL(ss.str(), "(0, 0, 0) (1, 2.5, 1.5)");
+
+        std::stringstream in("(1, 2, 3)  3 , 4, 5   2 5 1.5");
+        NUT_CHECK_EQUAL((in >> v1, v1), vec3(1.0f, 2.0f, 3.0f));
+        NUT_CHECK_EQUAL((in >> v1, v1), vec3(3.0f, 4.0f, 5.0f));
+        NUT_CHECK_EQUAL((in >> v1, v1), vec3(2.0f, 5.0f, 1.5f));
+    }
 }
+
+NUT_TESTGROUP(vector_comparisons) {
+
+    NUT_TESTCASE(different_sizes)
+    {
+        vec2 v1;
+        vec3 v2;
+        vec4 v3;
+
+        NUT_CHECK_NOT_EQUAL(v1, v2);
+        NUT_CHECK_NOT_EQUAL(v1, v3);
+        NUT_CHECK_NOT_EQUAL(v2, v3);
+    }
+
+    NUT_TESTCASE(different_types)
+    {
+        vec2 vf2(1.0f, 1.0f);
+        veci2 vi2(1, 1);
+        veci2 vi2b(2, 1);
+
+        NUT_CHECK_EQUAL(vf2, vi2);
+        NUT_CHECK_NOT_EQUAL(vf2, vi2b);
+
+        vec3 vf3(1.0f, 1.0f, 1.0f);
+        veci3 vi3(1, 1, 1);
+        veci3 vi3b(2, 1, 1);
+
+        NUT_CHECK_EQUAL(vf3, vi3);
+        NUT_CHECK_NOT_EQUAL(vf3, vi3b);
+
+        vec4 vf4(1.0f, 1.0f, 1.0f, 1.0f);
+        veci4 vi4(1, 1, 1, 1);
+        veci4 vi4b(2, 1, 1, 1);
+
+        NUT_CHECK_EQUAL(vf4, vi4);
+        NUT_CHECK_NOT_EQUAL(vf4, vi4b);
+    }
+}