diff options
author | Nao Pross <naopross@thearcway.org> | 2019-02-23 14:56:30 +0100 |
---|---|---|
committer | Nao Pross <naopross@thearcway.org> | 2019-02-23 15:03:55 +0100 |
commit | 4b97a0eb6c9ef2a0e8f53dd7d6f89129d8467fac (patch) | |
tree | a521c847616b3717c3fd55b47d2d33ed9581aee5 | |
parent | Merge branch 'master' into matrices (diff) | |
download | libmm-4b97a0eb6c9ef2a0e8f53dd7d6f89129d8467fac.tar.gz libmm-4b97a0eb6c9ef2a0e8f53dd7d6f89129d8467fac.zip |
Add initializer_list constructor to basic_matrix and matrix test
-rw-r--r-- | include/mmmatrix.hpp | 148 | ||||
-rw-r--r-- | test/CMakeLists.txt | 32 | ||||
-rw-r--r-- | test/matrix_example.cpp | 13 |
3 files changed, 143 insertions, 50 deletions
diff --git a/include/mmmatrix.hpp b/include/mmmatrix.hpp index d18f3f1..b973aba 100644 --- a/include/mmmatrix.hpp +++ b/include/mmmatrix.hpp @@ -13,12 +13,13 @@ #include <iostream> #include <cstring> +#include <cassert> +#include <initializer_list> namespace mm { template<typename T, std::size_t Rows, std::size_t Cols> class basic_matrix; - template<typename T, std::size_t Rows, std::size_t Cols> class matrix; @@ -43,73 +44,102 @@ public: static constexpr std::size_t rows = Rows; static constexpr std::size_t cols = Cols; + // from initializer_list + basic_matrix(std::initializer_list<std::initializer_list<T>> l); + + // copyable and movable basic_matrix(const basic_matrix<T, Rows, Cols>& other); basic_matrix(basic_matrix<T, Rows, Cols>&& other); + // copy from another matrix template<std::size_t ORows, std::size_t OCols> basic_matrix(const basic_matrix<T, ORows, OCols>& other); + // copy or move from 2D array basic_matrix(const T (& values)[Rows][Cols]); basic_matrix(T (&& values)[Rows][Cols]); // access data T& at(std::size_t row, std::size_t col); + const T& at(std::size_t row, std::size_t col) const; auto&& operator[](std::size_t index); void swap_rows(std::size_t x, std::size_t y); void swap_cols(std::size_t x, std::size_t y); // mathematical operations - basic_matrix<T, Cols, Rows> transposed(); - inline basic_matrix<T, Cols, Rows> trd() { return transposed(); } + basic_matrix<T, Cols, Rows> transposed() const; + inline basic_matrix<T, Cols, Rows> trd() const { return transposed(); } - // bool is_invertible(); - // bool invert(); - // basic_matrix<T, Rows, Cols> inverse(); + // bool is_invertible() const; + // basic_matrix<T, Rows, Cols> inverse() const; /// downcast to square matrix - inline constexpr bool is_square() { return (Rows == Cols); } - inline constexpr square_matrix<T, Rows> to_square() { + inline constexpr bool is_square() const { return (Rows == Cols); } + inline constexpr square_matrix<T, Rows> to_square() const { static_assert(is_square()); return static_cast<square_matrix<T, Rows>>(*this); } /// downcast to row_vector - inline constexpr bool is_row_vec() { return (Cols == 1); } - inline constexpr row_vec<T, Rows> to_row_vec() { + inline constexpr bool is_row_vec() const { return (Cols == 1); } + inline constexpr row_vec<T, Rows> to_row_vec() const { static_assert(is_row_vec()); return static_cast<row_vec<T, Rows>>(*this); } /// downcast to col_vector - inline constexpr bool is_col_vec() { return (Rows == 1); } - inline constexpr col_vec<T, Cols> to_col_vec() { + inline constexpr bool is_col_vec() const { return (Rows == 1); } + inline constexpr col_vec<T, Cols> to_col_vec() const { static_assert(is_col_vec()); return static_cast<col_vec<T, Cols>>(*this); } private: - T data[Rows][Cols] = {}; + T data[Rows * Cols] = {}; }; template<typename T, std::size_t Rows, std::size_t Cols> -mm::basic_matrix<T, Rows, Cols>::basic_matrix(const mm::basic_matrix<T, Rows, Cols>& other) { - for (int row = 0; row < Rows; row++) - for (int col = 0; col < Cols; col++) - data[row][col] = other.data[row][col]; +mm::basic_matrix<T, Rows, Cols>::basic_matrix( + std::initializer_list<std::initializer_list<T>> l +) { + assert(l.size() == Rows); + + auto row_it = l.begin(); + for (unsigned row = 0; (row < Rows) && (row_it != l.end()); row++) { + assert((*row_it).size() == Cols); + + auto col_it = (*row_it).begin(); + for (unsigned col = 0; (col < Cols) && (col_it != (*row_it).end()); col++) { + this->at(row, col) = *col_it; + ++col_it; + } + ++row_it; + } +} + +template<typename T, std::size_t Rows, std::size_t Cols> +mm::basic_matrix<T, Rows, Cols>::basic_matrix( + const mm::basic_matrix<T, Rows, Cols>& other +) { + std::memcpy(&data, &other.data, sizeof(data)); } template<typename T, std::size_t Rows, std::size_t Cols> -mm::basic_matrix<T, Rows, Cols>::basic_matrix(mm::basic_matrix<T, Rows, Cols>&& other) { +mm::basic_matrix<T, Rows, Cols>::basic_matrix( + mm::basic_matrix<T, Rows, Cols>&& other +) { data = other.data; } template<typename T, std::size_t Rows, std::size_t Cols> template<std::size_t ORows, std::size_t OCols> -mm::basic_matrix<T, Rows, Cols>::basic_matrix(const mm::basic_matrix<T, ORows, OCols>& other) { +mm::basic_matrix<T, Rows, Cols>::basic_matrix( + const mm::basic_matrix<T, ORows, OCols>& other +) { static_assert((ORows <= Rows), "cannot copy a taller matrix into a smaller one" ); @@ -118,9 +148,7 @@ mm::basic_matrix<T, Rows, Cols>::basic_matrix(const mm::basic_matrix<T, ORows, O "cannot copy a larger matrix into a smaller one" ); - for (int row = 0; row < Rows; row++) - for (int col = 0; col < Cols; col++) - data[row][col] = other.data[row][col]; + std::memcpy(&data, &other.data, sizeof(data)); } template<typename T, std::size_t Rows, std::size_t Cols> @@ -138,20 +166,32 @@ mm::basic_matrix<T, Rows, Cols>::basic_matrix(T (&& values)[Rows][Cols]) { template<typename T, std::size_t Rows, std::size_t Cols> T& mm::basic_matrix<T, Rows, Cols>::at(std::size_t row, std::size_t col) { - static_assert(row < Rows, "out of row bound"); - static_assert(col < Cols, "out of column bound"); + assert(row < Rows); // "out of row bound" + assert(col < Cols); // "out of column bound" + + return data[row * Cols + col]; +} + +template<typename T, std::size_t Rows, std::size_t Cols> +const T& mm::basic_matrix<T, Rows, Cols>::at(std::size_t row, std::size_t col) const { + assert(row < Rows); // "out of row bound" + assert(col < Cols); // "out of column bound" - return data[row][col]; + return data[row * Cols + col]; } template<typename T, std::size_t Rows, std::size_t Cols> auto&& mm::basic_matrix<T, Rows, Cols>::operator[](std::size_t index) { - if constexpr (is_row_vec()) - return data[0][index]; - else if constexpr (is_col_vec()) - return data[index][0]; + if constexpr (is_row_vec()) { + static_assert(index < Rows); + return data[index]; + } else if constexpr (is_col_vec()) { + static_assert(index < Cols); + return data[index]; + } - return row_vec<T, Rows>(std::move(data[index])); + // TODO: fix + // return row_vec<T, Rows>(std::move(data[index])); } template<typename T, std::size_t Rows, std::size_t Cols> @@ -159,8 +199,8 @@ void mm::basic_matrix<T, Rows, Cols>::swap_rows(std::size_t x, std::size_t y) { if (x == y) return; - for (int col = 0; col < Cols; col++) - std::swap(data[x][col], data[y][col]); + for (unsigned col = 0; col < Cols; col++) + std::swap(this->at(x, col), this->at(y, col)); } template<typename T, std::size_t Rows, std::size_t Cols> @@ -168,17 +208,17 @@ void mm::basic_matrix<T, Rows, Cols>::swap_cols(std::size_t x, std::size_t y) { if (x == y) return; - for (int row = 0; row < rows; row++) - std::swap(data[row][x], data[row][y]); + for (unsigned row = 0; row < rows; row++) + std::swap(this->at(row, x), this->at(row, y)); } template<typename T, std::size_t M, std::size_t N> -mm::basic_matrix<T, N, M> mm::basic_matrix<T, M, N>::transposed() { +mm::basic_matrix<T, N, M> mm::basic_matrix<T, M, N>::transposed() const { mm::basic_matrix<T, N, M> result; - for (int row = 0; row < M; row++) - for (int col = 0; col < N; col++) - result[row][col] = this[col][row]; + for (unsigned row = 0; row < M; row++) + for (unsigned col = 0; col < N; col++) + result.at(row, col) = this->at(row, col); return result; } @@ -192,8 +232,8 @@ mm::basic_matrix<T, Rows, Cols> operator+( ) { mm::basic_matrix<T, Rows, Cols> result; - for (int row = 0; row < Rows; row++) - for (int col = 0; col < Cols; col++) + for (unsigned row = 0; row < Rows; row++) + for (unsigned col = 0; col < Cols; col++) result.at(row, col) = a.at(row, col) + a.at(row, col); return result; @@ -205,8 +245,8 @@ mm::basic_matrix<T, Rows, Cols> operator*( const T& scalar ) { mm::basic_matrix<T, Rows, Cols> result; - for (int row = 0; row < Rows; row++) - for (int col = 0; col < Cols; col++) + for (unsigned row = 0; row < Rows; row++) + for (unsigned col = 0; col < Cols; col++) result.at(row, col) = m.at(row, col) * scalar; return result; @@ -228,8 +268,8 @@ mm::basic_matrix<T, M, N> operator*( mm::basic_matrix<T, M, N> result; // TODO: use a more efficient algorithm - for (int row = 0; row < M; row++) - for (int col = 0; col < N; col++) + for (unsigned row = 0; row < M; row++) + for (unsigned col = 0; col < N; col++) for (int k = 0; k < P; k++) result.at(row, col) = a.at(row, k) * b.at(k, col); @@ -247,12 +287,12 @@ mm::basic_matrix<T, Rows, Cols> operator-( template<typename T, std::size_t Rows, std::size_t Cols> std::ostream& operator<<(std::ostream& os, const mm::basic_matrix<T, Rows, Cols>& m) { - for (int row = 0; row < Rows; row++) { + for (unsigned row = 0; row < Rows; row++) { os << "[ "; - for (int col = 0; col < (Cols -1); col++) { - os << m.at(row, col); + for (unsigned col = 0; col < (Cols -1); col++) { + os << m.at(row, col) << ", "; } - os << m.at(Rows -1, Cols -1) << " ]\n"; + os << m.at(row, (Cols -1)) << " ]\n"; } return os; @@ -275,8 +315,8 @@ public: template<typename T, std::size_t N> void mm::square_matrix<T, N>::transpose() { - for (int row = 0; row < N; row++) - for (int col = 0; col < row; col++) + for (unsigned row = 0; row < N; row++) + for (unsigned col = 0; col < row; col++) std::swap(this->at(row, col), this->at(col, row)); } @@ -285,10 +325,18 @@ void mm::square_matrix<T, N>::transpose() { template<typename T, std::size_t Rows> class mm::row_vec : public mm::basic_matrix<T, Rows, 1> { public: + using mm::basic_matrix<T, Rows, 1>::basic_matrix; }; /* column vector specialization */ template<typename T, std::size_t Cols> class mm::col_vec : public mm::basic_matrix<T, 1, Cols> { public: + using mm::basic_matrix<T, 1, Cols>::basic_matrix; +}; + +template<typename T, std::size_t Rows, std::size_t Cols> +class mm::matrix : public mm::basic_matrix<T, Rows, Cols> { +public: + using mm::basic_matrix<T, Rows, Cols>::basic_matrix; }; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e80e737..89e7c47 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,4 @@ +# vectors example add_executable(vec_example vec_example.cpp ) @@ -26,3 +27,34 @@ target_link_libraries(vec_example PRIVATE MM::mm ) + + +# matrix example +add_executable(matrix_example + matrix_example.cpp +) + +target_compile_options(matrix_example + PRIVATE + $<$<CXX_COMPILER_ID:GNU>: + -pedantic -Wall -Wextra -Wcast-qual -Wcast-align -Wpointer-arith + -Winit-self -Wshadow -Wswitch-enum -Wredundant-decls -Wfloat-equal + -Wundef -Wvla -Wconversion -Wstrict-aliasing + > + $<$<CXX_COMPILER_ID:MSVC>:/W4> +) + +target_compile_features(matrix_example + PRIVATE + cxx_std_17 +) + +target_include_directories(matrix_example + PRIVATE + ${MM_INCLUDE_DIRS} +) + +target_link_libraries(matrix_example + PRIVATE + MM::mm +) diff --git a/test/matrix_example.cpp b/test/matrix_example.cpp new file mode 100644 index 0000000..3fb7c78 --- /dev/null +++ b/test/matrix_example.cpp @@ -0,0 +1,13 @@ +#include "mmmatrix.hpp" + +#include <iostream> +#include <complex> + +int main(int argc, char *argv[]) { + std::cout << "MxN dimensional (int) matrices" << std::endl; + mm::matrix<int, 3, 2> m {{1, 2}, {3, 4}, {5, 6}}; + + std::cout << m; + + return 0; +} |