Anonymous avatar Anonymous committed a34b02b

Added matrix module

Comments (0)

Files changed (11)

neglect/cpplib/CMakeLists.txt

 set(HEADERS
 	include/neglect/boot.hpp
 	include/neglect/exception.hpp
+	include/neglect/format.hpp
+	include/neglect/platform.hpp
 	include/neglect/vector.hpp
 	include/neglect/vector_io.hpp
-	include/neglect/format.hpp
-	include/neglect/platform.hpp
 	include/neglect/_vector2.hpp
 	include/neglect/_vector3.hpp
 	include/neglect/_vector4.hpp
+	include/neglect/matrix.hpp
+	include/neglect/matrix_io.hpp
 	include/neglect/unittest.hpp
 	include/neglect/path.hpp
 	include/neglect/ntpath.hpp

neglect/cpplib/include/neglect/_vector2.hpp

         };
 
         typedef T value_type;
+        static const size_t size = 2;
 
         // -- constructors
 
         {
         }
 
+        // -- pointer access
+
+        T* ptr() { return &x; }
+        const T* ptr() const { return &x; }
+
         // -- boolean checks
 
         operator bool() const
         {
             return math::sqrt(norm());
         }
-
-        size_t size() const { return 2; }
     };
 }
 

neglect/cpplib/include/neglect/_vector3.hpp

         };
 
         typedef T value_type;
+        static const size_t size = 3;
 
         // -- constructors
 
         {
         }
 
+        // -- pointer access
+
+        T* ptr() { return &x; }
+        const T* ptr() const { return &x; }
+
         // -- boolean checks
 
         operator bool() const
         {
             return math::sqrt(norm());
         }
-
-        size_t size() const { return 3; }
     };
 }
 

neglect/cpplib/include/neglect/_vector4.hpp

         };
 
         typedef T value_type;
+        static const size_t size = 4;
 
         // -- constructors
 
         {
         }
 
+        // -- pointer access
+
+        T* ptr() { return &x; }
+        const T* ptr() const { return &x; }
+
         // -- boolean checks
 
         operator bool() const
         {
             return math::sqrt(norm());
         }
-
-        size_t size() const { return 4; }
     };
 }
 

neglect/cpplib/include/neglect/matrix.hpp

+#ifndef _INC_NEGLECT_MATRIX_HPP_
+#define _INC_NEGLECT_MATRIX_HPP_
+
+#include <neglect/boot.hpp>
+#include <neglect/vector.hpp>
+
+namespace neglect {
+
+    template <typename T, size_t Width, size_t Height>
+    class matrix {
+    public:
+        static const size_t columns = Width;
+        static const size_t rows = Height;
+        static const size_t dimensions = Width * Height;
+
+        matrix()
+        {
+            set_zero();
+        }
+
+        template <class Sequence>
+        matrix(Sequence seq)
+        {
+            T *ptr = this->ptr();
+            for (int i = 0; i < dimensions; i++)
+                ptr[i] = seq[i];
+        }
+
+        static neglect::matrix<T, Width, Height> zero()
+        {
+            return neglect::matrix<T, Width, Height>();
+        }
+
+        static neglect::matrix<T, Width, Height> identity()
+        {
+            neglect::matrix<T, Width, Height> rv;
+            rv.set_identity();
+            return rv;
+        }
+
+        void set_zero()
+        {
+            std::fill_n(m_cols, Width, vector<T, Height>());
+        }
+
+        void set_identity()
+        {
+            BOOST_STATIC_ASSERT(Width == Height);
+            set_zero();
+            for (size_t i = 0; i < Width; i++)
+                m_cols[i][i] = T(1);
+        }
+
+        T *ptr()
+        {
+            return &m_cols[0].x;
+        }
+
+        const T *ptr() const
+        {
+            return &m_cols[0].x;
+        }
+
+        T &operator()(size_t column, size_t row)
+        {
+            return m_cols[column][row];
+        }
+
+        const T &operator()(size_t column, size_t row) const
+        {
+            return m_cols[column][row];
+        }
+
+        neglect::vector<T, Width> &operator[](size_t row)
+        {
+            return m_cols[row];
+        }
+
+        const neglect::vector<T, Width> &operator[](size_t row) const
+        {
+            return m_cols[row];
+        }
+
+    private:
+        neglect::vector<T, Height> m_cols[Width];
+    };
+
+    // common typedefs
+    typedef matrix<float, 2, 2> mat2;
+    typedef matrix<float, 3, 3> mat3;
+    typedef matrix<float, 4, 4> mat4;
+    typedef matrix<int, 2, 2> mati2;
+    typedef matrix<int, 3, 3> mati3;
+    typedef matrix<int, 4, 4> mati4;
+
+    /* checks if two matrices are amost equal */
+    template <typename TA, size_t WidthA, size_t HeightA,
+              typename TB, size_t WidthB, size_t HeightB>
+    bool operator==(const matrix<TA, WidthA, HeightA> &lhs,
+                    const matrix<TB, WidthB, HeightB> &rhs)
+    {
+        if (WidthA != WidthB || HeightA != HeightB)
+            return false;
+        const TA *ptr_a = lhs.ptr();
+        const TB *ptr_b = rhs.ptr();
+        for (size_t i = 0; i < lhs.dimensions; i++)
+            if (ptr_a[i] != ptr_b[i])
+                return false;
+        return true;
+    }
+
+    template <typename TA, size_t WidthA, size_t HeightA,
+              typename TB, size_t WidthB, size_t HeightB>
+    bool operator!=(const matrix<TA, WidthA, HeightA> &lhs,
+                    const matrix<TB, WidthB, HeightB> &rhs)
+    {
+        return !(lhs == rhs);
+    }
+
+    template <typename TA, size_t WidthA, size_t HeightA,
+              typename TB, size_t WidthB, size_t HeightB>
+    bool almost_equal(const matrix<TA, WidthA, HeightA> &lhs,
+                      const matrix<TB, WidthB, HeightB> &rhs)
+    {
+        if (WidthA != WidthB || HeightA != HeightB)
+            return false;
+        const TA *ptr_a = lhs.ptr();
+        const TB *ptr_b = rhs.ptr();
+        for (size_t i = 0; i < lhs.dimensions; i++)
+            if (!almost_equal(ptr_a[i], ptr_b[i]))
+                return false;
+        return true;
+    }
+}
+
+#endif

neglect/cpplib/include/neglect/matrix_io.hpp

+#ifndef _INC_NEGLECT_MATRIX_IO_HPP_
+#define _INC_NEGLECT_MATRIX_IO_HPP_
+
+#include <neglect/matrix.hpp>
+
+#include <iostream>
+
+namespace neglect {
+
+    template <typename T, size_t Width, size_t Height>
+    std::ostream &operator<<(std::ostream &lhs,
+        const neglect::matrix<T, Width, Height> &rhs)
+    {
+        lhs << "[";
+        for (size_t row = 0; row < Height; row++) {
+            if (row)
+                lhs << "," << std::endl << " ";
+            lhs << "[";
+            for (size_t column = 0; column < Width; column++) {
+                if (column)
+                    lhs << ", ";
+                lhs << rhs[column][row];
+            }
+            lhs << "]";
+        }
+        return lhs << "]";
+    }
+
+}
+
+#endif

neglect/cpplib/include/neglect/unittest.hpp

 
 /* helper macros to create testcases and groups */
 #define NUT_TESTGROUP(name)                                                 \
-    namespace BOOST_PP_CAT(name, _support) {                                \
+    namespace BOOST_PP_CAT(_, BOOST_PP_CAT(name, _support)) {               \
         static ::neglect::unittest::test_group *get_parent_test_group() {   \
             return get_neglect_test_group(__FILE__);                        \
         }                                                                   \
         static ::neglect::unittest::test_group                              \
             *get_neglect_test_group(const char *filename) {                 \
             static ::neglect::unittest::test_group the_group(#name,         \
-                BOOST_PP_CAT(name, _support)::get_parent_test_group(),      \
-                __FILE__);                                                  \
+                BOOST_PP_CAT(_, BOOST_PP_CAT(name, _support))               \
+                    ::get_parent_test_group(), __FILE__);                   \
             return &the_group;                                              \
         }                                                                   \
     }                                                                       \

neglect/cpplib/include/neglect/vector_io.hpp

     std::ostream &operator<<(std::ostream &lhs, const vector<T, Size> &rhs)
     {
         lhs << "(";
-        for (size_t i = 0; i < rhs.size(); i++) {
+        for (size_t i = 0; i < rhs.size; i++) {
             if (i)
                 lhs << ", ";
             lhs << rhs[i];
     {
         if (lhs.peek() == '(')
             lhs.get();
-        for (size_t i = 0; i < rhs.size(); i++) {
+        for (size_t i = 0; i < rhs.size; i++) {
             if (i) {
                 lhs >> std::ws;
                 if (lhs.peek() == ',')

neglect/tests/CMakeLists.txt

 set(SOURCES
     src/main.cpp
     src/test_vectors.cpp
+    src/test_matrix.cpp
     src/test_format.cpp
     src/test_path.cpp
     src/test_platform.cpp

neglect/tests/src/test_matrix.cpp

+#include <neglect/unittest.hpp>
+#include <neglect/matrix.hpp>
+#include <neglect/matrix_io.hpp>
+
+using namespace neglect;
+
+NUT_TESTGROUP(matrix4) {
+
+    NUT_TESTCASE(construction)
+    {
+        mat4 m1 = mat4::identity();
+        mat4 m2;
+        m2.set_identity();
+
+        NUT_CHECK_EQUAL(m1, m2);
+        NUT_CHECK_NOT_EQUAL(m1, mat4::zero());
+
+        float values[16] = { // think, transpose
+             1,  2,  3,  4,
+             5,  6,  7,  8,
+             9, 10, 11, 12,
+            13, 14, 15, 16
+        };
+        mat4 m3(values);
+        NUT_CHECK_EQUAL(m3[0], vec4(1, 2, 3, 4));
+        NUT_CHECK_EQUAL(m3[1], vec4(5, 6, 7, 8));
+        NUT_CHECK_EQUAL(m3[2], vec4(9, 10, 11, 12));
+        NUT_CHECK_EQUAL(m3[3], vec4(13, 14, 15, 16));
+        for (int i = 0; i < 16; i++)
+            NUT_CHECK_EQUAL(m3.ptr()[i], values[i]);
+
+        for (int i = 0; i < 4; i++)
+            for (int j = 0; j < 4; j++)
+                NUT_CHECK_EQUAL(m3[i][j], m3(i, j));
+    }
+}

neglect/tests/src/test_vectors.cpp

 #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)
+    (the_type::size == expected)
 
 
 using namespace neglect;
         NUT_CHECK(vec2);
         NUT_CHECK(static_cast<bool>(vec2));
 
-        NUT_REQUIRE_EQUAL(vec1.size(), 2);
-        NUT_REQUIRE_EQUAL(vec2.size(), 2);
-        NUT_REQUIRE_EQUAL(vec3.size(), 2);
+        NUT_REQUIRE_EQUAL(vec1.size, 2);
+        NUT_REQUIRE_EQUAL(vec2.size, 2);
+        NUT_REQUIRE_EQUAL(vec3.size, 2);
 
         NUT_CHECK_EQUAL(vec1.x, 0.0f);
         NUT_CHECK_EQUAL(vec1.y, 0.0f);
         NUT_CHECK_EQUAL(vec3.y, 6.0f);
     }
 
+    NUT_TESTCASE(pointer_access)
+    {
+        vec2 v(1.0f, 2.0f);
+        float *v_ptr = v.ptr();
+        NUT_CHECK_EQUAL(v_ptr[0], 1.0f);
+        NUT_CHECK_EQUAL(v_ptr[1], 2.0f);
+        v_ptr[0] = 0.0f;
+        v_ptr[1] = -1.0f;
+        NUT_CHECK_EQUAL(v.x, 0.0f);
+        NUT_CHECK_EQUAL(v.y, -1.0f);
+    }
+
     NUT_TESTCASE(modify_and_get)
     {
         vec2 v1;
         NUT_CHECK(vec2);
         NUT_CHECK(static_cast<bool>(vec2));
 
-        NUT_REQUIRE_EQUAL(vec1.size(), 3);
-        NUT_REQUIRE_EQUAL(vec2.size(), 3);
-        NUT_REQUIRE_EQUAL(vec3.size(), 3);
+        NUT_REQUIRE_EQUAL(vec1.size, 3);
+        NUT_REQUIRE_EQUAL(vec2.size, 3);
+        NUT_REQUIRE_EQUAL(vec3.size, 3);
 
         NUT_CHECK_EQUAL(vec1.x, 0.0f);
         NUT_CHECK_EQUAL(vec1.y, 0.0f);
         NUT_CHECK_EQUAL(vec3.z, 9.0f);
     }
 
+    NUT_TESTCASE(pointer_access)
+    {
+        vec3 v(1.0f, 2.0f, 3.0f);
+        float *v_ptr = v.ptr();
+        NUT_CHECK_EQUAL(v_ptr[0], 1.0f);
+        NUT_CHECK_EQUAL(v_ptr[1], 2.0f);
+        NUT_CHECK_EQUAL(v_ptr[2], 3.0f);
+        v_ptr[0] = 0.0f;
+        v_ptr[1] = -1.0f;
+        v_ptr[2] = -2.0f;
+        NUT_CHECK_EQUAL(v.x, 0.0f);
+        NUT_CHECK_EQUAL(v.y, -1.0f);
+        NUT_CHECK_EQUAL(v.z, -2.0f);
+    }
+
     NUT_TESTCASE(modify_and_get)
     {
         vec3 v1;
         NUT_CHECK(vec2);
         NUT_CHECK(static_cast<bool>(vec2));
 
-        NUT_REQUIRE_EQUAL(vec1.size(), 4);
-        NUT_REQUIRE_EQUAL(vec2.size(), 4);
-        NUT_REQUIRE_EQUAL(vec3.size(), 4);
+        NUT_REQUIRE_EQUAL(vec1.size, 4);
+        NUT_REQUIRE_EQUAL(vec2.size, 4);
+        NUT_REQUIRE_EQUAL(vec3.size, 4);
 
         NUT_CHECK_EQUAL(vec1.x, 0.0f);
         NUT_CHECK_EQUAL(vec1.y, 0.0f);
         NUT_CHECK_EQUAL(vec3.w, 12.0f);
     }
 
+    NUT_TESTCASE(pointer_access)
+    {
+        vec4 v(1.0f, 2.0f, 3.0f, 4.0f);
+        float *v_ptr = v.ptr();
+        NUT_CHECK_EQUAL(v_ptr[0], 1.0f);
+        NUT_CHECK_EQUAL(v_ptr[1], 2.0f);
+        NUT_CHECK_EQUAL(v_ptr[2], 3.0f);
+        NUT_CHECK_EQUAL(v_ptr[3], 4.0f);
+        v_ptr[0] = 0.0f;
+        v_ptr[1] = -1.0f;
+        v_ptr[2] = -2.0f;
+        v_ptr[3] = -3.0f;
+        NUT_CHECK_EQUAL(v.x, 0.0f);
+        NUT_CHECK_EQUAL(v.y, -1.0f);
+        NUT_CHECK_EQUAL(v.z, -2.0f);
+        NUT_CHECK_EQUAL(v.w, -3.0f);
+    }
+
     NUT_TESTCASE(modify_and_get)
     {
         vec4 v1;
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.