summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNao Pross <naopross@thearcway.org>2019-02-23 14:56:30 +0100
committerNao Pross <naopross@thearcway.org>2019-02-23 15:03:55 +0100
commit4b97a0eb6c9ef2a0e8f53dd7d6f89129d8467fac (patch)
treea521c847616b3717c3fd55b47d2d33ed9581aee5
parentMerge branch 'master' into matrices (diff)
downloadlibmm-4b97a0eb6c9ef2a0e8f53dd7d6f89129d8467fac.tar.gz
libmm-4b97a0eb6c9ef2a0e8f53dd7d6f89129d8467fac.zip
Add initializer_list constructor to basic_matrix and matrix test
-rw-r--r--include/mmmatrix.hpp148
-rw-r--r--test/CMakeLists.txt32
-rw-r--r--test/matrix_example.cpp13
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;
+}