Anonymous avatar Anonymous committed b8e890d

Improved vector test support.

Comments (0)

Files changed (11)

neglect/cpplib/CMakeLists.txt

 	include/neglect/boot.hpp
 	include/neglect/exception.hpp
 	include/neglect/vector.hpp
+	include/neglect/vector_io.hpp
 	include/neglect/format.hpp
 	include/neglect/platform.hpp
 	include/neglect/_vector2.hpp

neglect/cpplib/include/neglect/_vector2.hpp

 
         T &operator[](const size_t idx)
         {
-            assert(x < 2);
+            assert(idx < 2);
             return *(&x + idx);
         }
 
         T operator[](const size_t idx) const
         {
-            assert(x < 2);
+            assert(idx < 2);
             return *(&x + idx);
         }
 

neglect/cpplib/include/neglect/_vector3.hpp

 
         T &operator[](const size_t idx)
         {
-            assert(x < 3);
+            assert(idx < 3);
             return *(&x + idx);
         }
 
         T operator[](const size_t idx) const
         {
-            assert(x < 3);
+            assert(idx < 3);
             return *(&x + idx);
         }
 

neglect/cpplib/include/neglect/_vector4.hpp

 
         T &operator[](const size_t idx)
         {
-            assert(x < 4);
+            assert(idx < 4);
             return *(&x + idx);
         }
 
         T operator[](const size_t idx) const
         {
-            assert(x < 4);
+            assert(idx < 4);
             return *(&x + idx);
         }
 

neglect/cpplib/include/neglect/boot.hpp

     // if tr1 is unavailable, boost will add that for us.
     using std::tr1::shared_ptr;
     using boost::shared_array;
-
-    // currently these are just aliases to the C/C++ math functions
-    // but this gives the possibility to replace them later with more
-    // optimized functions
-    namespace math {
-        using std::sqrt;
-    }
 }
 
 // standard exception class

neglect/cpplib/include/neglect/math.hpp

+#ifndef _INC_NEGLECT_MATH_HPP_
+#define _INC_NEGLECT_MATH_HPP_
+
+#include <neglect/boot.hpp>
+
+namespace neglect {
+
+    /* check if two numeric values are almost equal */
+    inline bool almost_equal(int a, int b)
+    {
+        return a == b;
+    }
+
+    inline bool almost_equal(size_t a, size_t b)
+    {
+        return a == b;
+    }
+
+    inline bool almost_equal(float a, float b)
+    {
+        return (a - 1e-06 < b && a + 1e-06 > b);
+    }
+
+    inline bool almost_equal(double a, double b)
+    {
+        return (a - 1e-08 < b && a + 1e-08 > b);
+    }
+
+    // currently these are just aliases to the C/C++ math functions
+    // but this gives the possibility to replace them later with more
+    // optimized functions
+    namespace math {
+        using std::sqrt;
+    }
+}
+
+#endif

neglect/cpplib/include/neglect/unittest.hpp

 /* implements a lightweight unittest system purely with templates
    and macros which is primarily used to test neglect itself, but
-   can also be used to test other cpp and c libraries */
+   can also be used to test other cpp and c libraries.
+   
+   Currently a lot here is a bad hack, but at least it can be used
+   for basic testing without external dependencies besides boost. */
 
 #include <neglect/boot.hpp>
+#include <neglect/math.hpp>
 
 #include <fstream>
 #include <sstream>
             return false;
         }
 
+        template <class A, class B>
+        bool check_almost_equal(A a, B b, const location &loc)
+        {
+            if (almost_equal(a, b))
+                return true;
+
+            std::stringstream details;
+            details << "expression: " << a << " almost equal to " << b;
+
+            test_error err;
+            err.loc = loc;
+            err.type = "Almost-Equality check failed";
+            err.message = "the two objects are too different";
+            err.details = details.str();
+            record_test_error(err);
+            return false;
+        }
+
         void print_summary()
         {
             m_stream << "Ran " << test_count() << " test(s)" << std::endl;
                 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;
 #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_CHECK(expr) runner.check(expr, #expr, _NUT_LOCATION)
-#define NUT_CHECK_EQUAL(a, b) runner.check_equal(a, b, _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)

neglect/cpplib/include/neglect/vector.hpp

     typedef vector<int, 3> veci3;
     typedef vector<int, 4> veci4;
 
-#if 0
+    /* 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)
+    {
+        for (size_t i = 0; i < Size; i++)
+            if (!almost_equal(lhs[i], rhs[i]))
+                return false;
+        return true;
+    }
+
     /* normalizes a vector.  If the vector is close to zero or zero, nothing
        is done instead.  This should avoid common errors where a code tries
        to operate on an unknown vector.  If the vector is close to 0, nothing
        is done instead. */
     template <typename T, size_t Size>
-    normalize(const vector<T, Size> &vec)
+    vector<T, Size> normalize(const vector<T, Size> &vec)
     {
         T length = vec.length();
-        return (length > 1e-08) ? vec /= length : vec;
+        return (length > 1e-08) ? vec / length : vec;
     }
 
     /* calculates the cross product of two two-dimensional vectors */
     template <typename T>
     T cross(const vector<T, 2> &lhs, const vector<T, 2> &rhs)
     {
-        return lhs.x * rhs.y - y * rhs.x;
+        return lhs.x * rhs.y - lhs.y * rhs.x;
     }
 
     /* calculates the cross product of two three-dimensional vectors */
     template <typename T>
-    T cross(const vector<T, 3> &lhs, const vector<T, 3> &rhs)
+    vector<T, 3> cross(const vector<T, 3> &lhs, const vector<T, 3> &rhs)
     {
         return vector<T, 3>(lhs.y * rhs.z - lhs.z * rhs.y,
                             lhs.z * rhs.x - lhs.x * rhs.z,
 
     /* calculates the dot product of two four-dimensional vectors */
     template <typename T>
-    T dot(const vector<T, 3> &lhs, const vector<T, 3> &rhs)
+    T dot(const vector<T, 4> &lhs, const vector<T, 4> &rhs)
     {
         return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z + lhs.w * lhs.w;
     }
 
     /* returns a perpendicular vector */
-    template <typename T, size_t Size>
-    vector<T, Size> perpendicular(const vector<T, Size> &vec)
+    template <typename T>
+    vector<T, 2> perpendicular(const vector<T, 2> &vec)
     {
-        return vector<T, Size>(-vec.y, vec.x);
+        return vector<T, 2>(-vec.y, vec.x);
     }
 
+#if 0
     /* returns a reflection vector to the plane with the given normal vector. */
     template <typename T, size_t Size>
     vector<T, Size> reflect(const vector<T, Size> &vec,

neglect/cpplib/include/neglect/vector_io.hpp

+#ifndef _INC_NEGLECT_VECTOR_IO_HPP_
+#define _INC_NEGLECT_VECTOR_IO_HPP_
+
+#include <neglect/vector.hpp>
+
+#include <iostream>
+
+namespace neglect {
+
+    template <typename T, size_t Size>
+    std::ostream &operator<<(std::ostream &lhs, const vector<T, Size> &rhs)
+    {
+        lhs << "(";
+        for (size_t i = 0; i < rhs.size(); i++) {
+            if (i)
+                lhs << ", ";
+            lhs << rhs[i];
+        }
+        return lhs << ")";
+    }
+
+    template <typename T, size_t Size>
+    std::istream &operator>>(std::istream &lhs, vector<T, Size> &rhs)
+    {
+        if (lhs.peek() == '(')
+            lhs.get();
+        for (size_t i = 0; i < rhs.size(); i++) {
+            if (i) {
+                lhs >> std::ws;
+                if (lhs.peek() == ',')
+                    lhs.get();
+            }
+            lhs >> rhs[i];
+        }
+        if (lhs.peek() == ')')
+            lhs.get();
+        return lhs;
+    }
+
+}
+
+#endif

neglect/tests/src/main.cpp

     runner.test_all();
 
 #if NEGLECT_PLATFORM == NEGLECT_PLATFORM_WINDOWS
-    std::cerr << "Press any key to continue ..." << std::endl;
+    std::cerr << std::endl << "Press any key to continue ..." << std::endl;
     getc(stdin);
 #endif
 

neglect/tests/src/test_vectors.cpp

 #include <neglect/unittest.hpp>
 #include <neglect/vector.hpp>
+#include <neglect/vector_io.hpp>
+
+#include <sstream>
 
 
 using namespace neglect;
 
 NUT_TESTGROUP(vector2) {
 
-    NUT_TESTCASE(basic_operations)
+    NUT_TESTCASE(constructors)
     {
         vector<float, 2> vec1;
         vector<float, 2> vec2(1.0f, 2.0f);
         NUT_CHECK_EQUAL(vec2.y, 2.0f);
     }
 
+    NUT_TESTCASE(basic_math)
+    {
+        vec2 v1(1.5f, -2.5f);
+        vec2 v2(1.0f, 2.0f);
+
+        NUT_CHECK_EQUAL(v1 + v2, vec2(2.5f, -0.5f));
+        NUT_CHECK_EQUAL(v1 - v2, vec2(0.5f, -4.5f));
+        NUT_CHECK_EQUAL(v1 * v2, vec2(1.5f, -5.0f));
+        NUT_CHECK_EQUAL(v1 / v2, vec2(1.5f, -1.25f));
+        NUT_CHECK_EQUAL(-v1, vec2(-1.5f, 2.5f));
+    }
+
+    NUT_TESTCASE(vector_functions)
+    {
+        vec2 v1(1.5f, 0.0f);
+        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.707107f, 0.707107f));
+        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_TESTCASE(stream_support)
+    {
+        std::stringstream ss;
+        vector<float, 2> v1;
+        vector<float, 2> v2(1.0f, 2.5f);
+
+        ss << v1 << " " << v2;
+
+        NUT_CHECK_EQUAL(ss.str(), "(0, 0) (1, 2.5)");
+
+        std::stringstream in("(1, 2)  3 , 4 2 5");
+        NUT_CHECK_EQUAL((in >> v1, v1), vec2(1.0f, 2.0f));
+        NUT_CHECK_EQUAL((in >> v1, v1), vec2(3.0f, 4.0f));
+        NUT_CHECK_EQUAL((in >> v1, v1), vec2(2.0f, 5.0f));
+    }
+
 }
-
-
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.