diff --git a/include/DataFrame/Utils/Matrix.h b/include/DataFrame/Utils/Matrix.h index 964b3897..fff70908 100644 --- a/include/DataFrame/Utils/Matrix.h +++ b/include/DataFrame/Utils/Matrix.h @@ -53,15 +53,20 @@ class Matrix { public: - using size_type = std::size_t; + using size_type = long; using value_type = T; using reference = value_type &; using const_reference = const value_type &; using pointer = value_type *; using const_pointer = const value_type *; - using self_t = Matrix; + using trans_result_t = + typename std::conditional< + MO == matrix_orient::column_major, + Matrix, + Matrix>::type; + Matrix() = default; Matrix(size_type rows, size_type cols, const_reference def_v = T()); Matrix(const Matrix &) = default; @@ -99,6 +104,9 @@ class Matrix { template void set_row(I row_data, size_type row); + trans_result_t transpose() const noexcept; + Matrix transpose2() const noexcept; + private: using storage_t = std::vector; @@ -114,7 +122,7 @@ class Matrix { public: class row_iterator; - class row_const_iterator : public std::random_access_iterator_tag { + class row_const_iterator : public std::random_access_iterator_tag { public: @@ -127,8 +135,6 @@ class Matrix { using const_reference = const value_type &; using difference_type = typename std::vector::difference_type; - public: - inline row_const_iterator () = default; inline row_const_iterator(const self_t *m, @@ -189,6 +195,10 @@ class Matrix { col_ += 1; if (col_ >= mptr_->cols()) { col_ = 0; row_ += 1; } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (*this); } inline row_const_iterator operator ++ (int) noexcept { // Postfix++ @@ -198,6 +208,10 @@ class Matrix { col_ += 1; if (col_ >= mptr_->cols()) { col_ = 0; row_ += 1; } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (row_const_iterator (mptr_, row, col)); } @@ -208,6 +222,10 @@ class Matrix { row_ += col_ / mptr_->cols(); col_ %= mptr_->cols(); } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (*this); } @@ -247,6 +265,10 @@ class Matrix { row_ += col_ / mptr_->cols(); col_ %= mptr_->cols(); } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (row_const_iterator (mptr_, row, col)); } @@ -279,7 +301,7 @@ class Matrix { const size_type row_diff = lhs.row_ - rhs.row_; const size_type col_diff = lhs.col_ - rhs.col_; - assert(lhs.mptr_ == rhs.mptr); + assert(lhs.mptr_ == rhs.mptr_); return (difference_type( std::abs(row_diff) * rhs.mptr_->cols() - col_diff)); } @@ -293,7 +315,7 @@ class Matrix { // It goes through the matrix row-by-row starting at [0, 0] // - class row_iterator : public std::random_access_iterator_tag { + class row_iterator : public std::random_access_iterator_tag { public: @@ -362,6 +384,10 @@ class Matrix { col_ += 1; if (col_ >= mptr_->cols()) { col_ = 0; row_ += 1; } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (*this); } inline row_iterator operator ++ (int) noexcept { // Postfix++ @@ -371,6 +397,10 @@ class Matrix { col_ += 1; if (col_ >= mptr_->cols()) { col_ = 0; row_ += 1; } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (row_iterator (mptr_, row, col)); } @@ -381,6 +411,10 @@ class Matrix { row_ += col_ / mptr_->cols(); col_ %= mptr_->cols(); } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (*this); } @@ -420,6 +454,10 @@ class Matrix { row_ += col_ / mptr_->cols(); col_ %= mptr_->cols(); } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (row_iterator (mptr_, row, col)); } @@ -449,10 +487,11 @@ class Matrix { friend difference_type operator - (row_iterator lhs, row_iterator rhs) noexcept { + assert(lhs.mptr_ == rhs.mptr_); + const size_type row_diff = lhs.row_ - rhs.row_; const size_type col_diff = lhs.col_ - rhs.col_; - assert(lhs.mptr_ == rhs.mptr); return (difference_type( std::abs(row_diff) * rhs.mptr_->cols() - col_diff)); } @@ -465,7 +504,7 @@ class Matrix { }; class col_iterator; - class col_const_iterator : public std::random_access_iterator_tag { + class col_const_iterator : public std::random_access_iterator_tag { public: @@ -540,6 +579,10 @@ class Matrix { row_ += 1; if (row_ >= mptr_->rows()) { row_ = 0; col_ += 1; } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (*this); } inline col_const_iterator operator ++ (int) noexcept { // Postfix++ @@ -549,6 +592,10 @@ class Matrix { row_ += 1; if (row_ >= mptr_->rows()) { row_ = 0; col_ += 1; } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (col_const_iterator (mptr_, row, col)); } @@ -559,6 +606,10 @@ class Matrix { col_ += row_ / mptr_->rows(); row_ %= mptr_->rows(); } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (*this); } @@ -598,6 +649,10 @@ class Matrix { col_ += row_ / mptr_->rows(); row_ %= mptr_->rows(); } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (col_const_iterator (mptr_, row, col)); } @@ -627,12 +682,13 @@ class Matrix { friend difference_type operator - (col_const_iterator lhs, col_const_iterator rhs) noexcept { + assert(lhs.mptr_ == rhs.mptr_); + const size_type row_diff = lhs.row_ - rhs.row_; const size_type col_diff = lhs.col_ - rhs.col_; - assert(lhs.mptr_ == rhs.mptr); return (difference_type( - std::abs(row_diff) * rhs.mptr_->cols() - col_diff)); + std::abs(col_diff) * rhs.mptr_->rows() - row_diff)); } private: @@ -644,7 +700,7 @@ class Matrix { // It goes through the matrix row-by-row starting at [0, 0] // - class col_iterator : public std::random_access_iterator_tag { + class col_iterator : public std::random_access_iterator_tag { public: @@ -713,6 +769,10 @@ class Matrix { row_ += 1; if (row_ >= mptr_->rows()) { row_ = 0; col_ += 1; } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (*this); } inline col_iterator operator ++ (int) noexcept { // Postfix++ @@ -722,6 +782,10 @@ class Matrix { row_ += 1; if (row_ >= mptr_->rows()) { row_ = 0; col_ += 1; } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (col_iterator (mptr_, row, col)); } @@ -732,6 +796,10 @@ class Matrix { col_ += row_ / mptr_->rows(); row_ %= mptr_->rows(); } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (*this); } @@ -771,6 +839,10 @@ class Matrix { col_ += row_ / mptr_->rows(); row_ %= mptr_->rows(); } + if (col_ >= mptr_->cols() || row_ >= mptr_->rows()) { + col_ = mptr_->cols(); + row_ = mptr_->rows(); + } return (col_iterator (mptr_, row, col)); } @@ -803,9 +875,9 @@ class Matrix { const size_type row_diff = lhs.row_ - rhs.row_; const size_type col_diff = lhs.col_ - rhs.col_; - assert(lhs.mptr_ == rhs.mptr); + assert(lhs.mptr_ == rhs.mptr_); return (difference_type( - std::abs(row_diff) * rhs.mptr_->cols() - col_diff)); + std::abs(col_diff) * rhs.mptr_->rows() - row_diff)); } private: diff --git a/include/DataFrame/Utils/Matrix.tcc b/include/DataFrame/Utils/Matrix.tcc index f6c03e2d..9f50bd98 100644 --- a/include/DataFrame/Utils/Matrix.tcc +++ b/include/DataFrame/Utils/Matrix.tcc @@ -170,6 +170,50 @@ template constexpr matrix_orient Matrix::orientation() { return (MO); } +// ---------------------------------------------------------------------------- + +template +Matrix::trans_result_t +Matrix::transpose() const noexcept { + + trans_result_t result { cols(), rows() }; + + if constexpr (MO == matrix_orient::column_major) { + for (size_type c = 0; c < cols(); ++c) + for (size_type r = 0; r < rows(); ++r) + result(c, r) = at(r, c); + } + else { + for (size_type r = 0; r < rows(); ++r) + for (size_type c = 0; c < cols(); ++c) + result(c, r) = at(r, c); + } + + return (result); +} + +// ---------------------------------------------------------------------------- + +template +Matrix +Matrix::transpose2() const noexcept { + + Matrix result { cols(), rows() }; + + if constexpr (MO == matrix_orient::column_major) { + for (size_type c = 0; c < cols(); ++c) + for (size_type r = 0; r < rows(); ++r) + result(c, r) = at(r, c); + } + else { + for (size_type r = 0; r < rows(); ++r) + for (size_type c = 0; c < cols(); ++c) + result(c, r) = at(r, c); + } + + return (result); +} + } // namespace hmdf // ---------------------------------------------------------------------------- diff --git a/test/matrix_tester.cc b/test/matrix_tester.cc index 5ed370e0..b47f735c 100644 --- a/test/matrix_tester.cc +++ b/test/matrix_tester.cc @@ -37,8 +37,8 @@ using namespace hmdf; using row_mat_t = Matrix; using col_mat_t = Matrix; -static constexpr std::size_t ROWS = 5; -static constexpr std::size_t COLS = 6; +static constexpr long ROWS = 5; +static constexpr long COLS = 6; // ----------------------------------------------------------------------------- @@ -48,25 +48,76 @@ int main(int, char *[]) { col_mat_t col_mat { ROWS, COLS }; std::size_t value { 0 }; - for (std::size_t r = 0; r < row_mat.rows(); ++r) - for (std::size_t c = 0; c < row_mat.cols(); ++c) + for (long r = 0; r < row_mat.rows(); ++r) + for (long c = 0; c < row_mat.cols(); ++c) row_mat(r, c) = value++; value = 0; - for (std::size_t c = 0; c < col_mat.cols(); ++c) - for (std::size_t r = 0; r < col_mat.rows(); ++r) + for (long c = 0; c < col_mat.cols(); ++c) + for (long r = 0; r < col_mat.rows(); ++r) col_mat(r, c) = value++; + // Print the stuff out + // + for (long r = 0; r < row_mat.rows(); ++r) { + for (long c = 0; c < row_mat.cols(); ++c) { + std::cout << row_mat(r, c) << ", "; + } + std::cout << '\n'; + } + std::cout << "\n\n"; + for (long r = 0; r < col_mat.rows(); ++r) { + for (long c = 0; c < col_mat.cols(); ++c) { + std::cout << col_mat(r, c) << ", "; + } + std::cout << '\n'; + } + value = 0; - for (std::size_t r = 0; r < row_mat.rows(); ++r) - for (std::size_t c = 0; c < row_mat.cols(); ++c) + for (long r = 0; r < row_mat.rows(); ++r) + for (long c = 0; c < row_mat.cols(); ++c) assert(row_mat(r, c) == value++); value = 0; - for (std::size_t c = 0; c < col_mat.cols(); ++c) - for (std::size_t r = 0; r < col_mat.rows(); ++r) + for (long c = 0; c < col_mat.cols(); ++c) + for (long r = 0; r < col_mat.rows(); ++r) assert(col_mat(r, c) == value++); + value = 0; + for (auto citer = row_mat.row_cbegin(); + citer != row_mat.row_cend(); ++citer) + assert(*citer == value++); + + value = 0; + for (auto citer = col_mat.col_cbegin(); + citer != col_mat.col_cend(); ++citer) + assert(*citer == value++); + + col_mat_t empty_mat { }; + + assert(empty_mat.empty()); + assert(empty_mat.rows() == 0); + assert(empty_mat.cols() == 0); + for (auto citer = empty_mat.row_cbegin(); + citer != empty_mat.row_cend(); ++citer) + assert(*citer == value++); + + auto col_iter1 = col_mat.col_begin(); + auto col_iter2 = col_mat.col_begin(); + auto row_iter1 = col_mat.row_begin(); + auto row_iter2 = col_mat.row_begin(); + + col_iter2 += 7; + row_iter2 += 7; + + assert(*col_iter1 == 0); + assert(*row_iter1 == 0); + assert(*col_iter2 == 7); + assert(*row_iter2 == 6); + + assert(((col_iter1 - col_iter2) == 7)); + assert(((row_iter1 - row_iter2) == 7)); + return (0); }