32 #ifndef MCKL_CORE_MATRIX_HPP 33 #define MCKL_CORE_MATRIX_HPP 48 typename Alloc = Allocator<T>>
51 using layout_dispatch = std::integral_constant<MatrixLayout, Layout>;
52 using row_major = std::integral_constant<MatrixLayout, RowMajor>;
53 using col_major = std::integral_constant<MatrixLayout, ColMajor>;
73 std::conditional_t<Layout == RowMajor, pointer, StepIterator<pointer>>;
78 std::reverse_iterator<const_row_iterator>;
81 std::conditional_t<Layout == ColMajor, pointer, StepIterator<pointer>>;
86 std::reverse_iterator<const_col_iterator>;
103 std::is_nothrow_default_constructible<
Vector<T, Alloc>>::value)
110 : data_(nrow * ncol), nrow_(nrow), ncol_(ncol)
120 : data_(
std::move(other.data_)), nrow_(other.nrow_), ncol_(other.ncol_)
131 noexcept(data_.swap(other.data_)))
133 if (
this != &other) {
134 data_.swap(other.data_);
135 std::swap(nrow_, other.nrow_);
136 std::swap(ncol_, other.ncol_);
213 return row_begin_dispatch(i, layout_dispatch());
222 return row_begin_dispatch(i, layout_dispatch());
276 return col_begin_dispatch(i, layout_dispatch());
285 return col_begin_dispatch(j, layout_dispatch());
405 runtime_assert<std::out_of_range>(
406 i < nrow_,
"**Matrix::at** row index out of range");
407 runtime_assert<std::out_of_range>(
408 j < ncol_,
"**Matrix::at** column index out of range");
410 return at_dispatch(i, j, layout_dispatch());
416 runtime_assert<std::out_of_range>(
417 i < nrow_,
"**Matrix::at** row index out of range");
418 runtime_assert<std::out_of_range>(
419 j < ncol_,
"**Matrix::at** column index out of range");
421 return at_dispatch(i, j, layout_dispatch());
427 return at_dispatch(i, j, layout_dispatch());
433 return at_dispatch(i, j, layout_dispatch());
445 return row_data_dispatch(i, layout_dispatch());
451 return row_data_dispatch(i, layout_dispatch());
457 return row_stride_dispatch(layout_dispatch());
463 return col_data_dispatch(j, layout_dispatch());
469 return col_data_dispatch(j, layout_dispatch());
475 return col_stride_dispatch(layout_dispatch());
482 bool empty()
const {
return nrow_ == 0 || ncol_ == 0; }
508 if (nrow * ncol == 0) {
515 if (nrow == nrow_ && ncol_ == ncol) {
519 resize_dispatch(nrow, ncol, layout_dispatch());
534 template <
typename InputIter>
538 std::copy_n(first, ncol_,
row_begin(nrow_ - 1));
542 template <
typename InputIter>
546 std::copy_n(first, nrow_,
col_begin(ncol_ - 1));
550 void swap(
Matrix &other) noexcept(noexcept(data_.swap(other.data_)))
552 std::swap(nrow_, other.nrow_);
553 std::swap(ncol_, other.ncol_);
554 data_.swap(other.data_);
566 if (m1.nrow_ != m2.nrow_) {
569 if (m1.ncol_ != m2.ncol_) {
572 return m1.data_ == m2.data_;
584 if (m1.nrow_ != m2.nrow_) {
587 if (m1.ncol_ != m2.ncol_) {
590 return is_equal(m1.data_, m2.data_);
599 size_type ldim_dispatch(row_major)
const {
return ncol_; }
614 StepIterator<const_pointer> col_begin_dispatch(
617 return StepIterator<const_pointer>(
623 return data_[i * ncol_ + j];
628 return data_[i * ncol_ + j];
631 size_type row_stride_dispatch(row_major)
const {
return 1; }
635 return data() + i * ncol_;
640 return data() + i * ncol_;
643 size_type col_stride_dispatch(row_major)
const {
return ncol_; }
655 data_.resize(nrow * ncol);
661 const size_type n = std::min(nrow, nrow_);
662 const size_type m = std::min(ncol, ncol_);
671 size_type ldim_dispatch(col_major)
const {
return nrow_; }
679 StepIterator<const_pointer> row_begin_dispatch(
682 return StepIterator<const_pointer>(
695 return data_[j * nrow_ + i];
700 return data_[j * nrow_ + i];
703 size_type row_stride_dispatch(col_major)
const {
return nrow_; }
712 size_type col_stride_dispatch(col_major)
const {
return 1; }
716 return data() + j * nrow_;
721 return data() + j * nrow_;
727 data_.resize(nrow * ncol);
733 const size_type n = std::min(nrow, nrow_);
734 const size_type m = std::min(ncol, ncol_);
743 template <
typename CharT,
typename Traits,
typename T,
MatrixLayout Layout,
752 os << mat.
nrow() <<
' ' << mat.
ncol();
757 for (std::size_t j = 0; j != mat.
ncol(); ++j) {
758 for (std::size_t i = 0; i != mat.
nrow(); ++i) {
759 os <<
' ' << mat(i, j);
767 template <
typename CharT,
typename Traits,
typename T,
MatrixLayout Layout,
776 std::size_t
nrow = 0;
777 std::size_t
ncol = 0;
778 is >> nrow >> std::ws >>
ncol;
784 for (std::size_t j = 0; j != mat.
ncol(); ++j) {
785 for (std::size_t i = 0; i != mat.
nrow(); ++i) {
786 is >> std::ws >> tmp(i, j);
790 mat = std::move(tmp);
798 #endif // MCKL_CORE_MATRIX_HPP const_col_range col(size_type i) const
Range of a column.
std::conditional_t< Layout==RowMajor, const_pointer, StepIterator< const_pointer > > const_row_iterator
Range< const_reverse_row_iterator > const_reverse_row_range
const_reverse_col_iterator col_rend(size_type j) const
Iterator to one before the beginning of a column.
const_col_range ccol(size_type i) const
Range of a column.
Matrix(size_type nrow, size_type ncol)
Construct an nrow by ncol matrix.
std::reverse_iterator< const_row_iterator > const_reverse_row_iterator
void clear()
Clear the matrix of all elements.
allocator_type get_allocator() const
Return the associated allocator.
size_type ncol() const
The number of columns.
void resize(size_type nrow, size_type ncol)
Resize the matrix.
Matrix() noexcept(std::is_nothrow_default_constructible< Vector< T, Alloc >>::value)
Construct an empty matrix.
friend bool operator==(const Matrix &m1, const Matrix &m2)
Compare equality.
const_row_iterator row_cbegin(size_type i) const
Iterator to the beginning of a row.
reverse_col_iterator col_rbegin(size_type j)
Iterator to the end of a column.
const_col_iterator col_end(size_type j) const
Iterator to one pass the end of a column.
const_iterator begin() const
Iterator to the upper left corner of the matrix.
reverse_row_iterator row_rbegin(size_type i)
Iterator to the end of a row.
Range< reverse_row_iterator > reverse_row_range
const_reference operator()(size_type i, size_type j) const
Access an element in the matrix.
const_iterator end() const
Iterator to one pass the lower right corner of the matrix.
const_reverse_iterator rend() const
Iterator one before the upper left corner of the matrix.
std::vector< T, Alloc > Vector
std::vector with Allocator as the default allocator
std::reverse_iterator< col_iterator > reverse_col_iterator
void swap(Matrix &other) noexcept(noexcept(data_.swap(other.data_)))
Swap two matrices.
const_reverse_iterator crend() const
Iterator one before the upper left corner of the matrix.
const_row_iterator row_end(size_type i) const
Iterator to one pass the end of a row.
Range< const_row_iterator > const_row_range
bool empty() const
If the matrix is empty, i.e., nrow() * ncol() == 0
const_reverse_iterator rbegin() const
Iterator to the lower right corner of the matrix.
const_reference at(size_type i, size_type j) const
Access an element in the matrix with bound checking.
std::reverse_iterator< const_iterator > const_reverse_iterator
const_pointer row_data(size_type i) const
Pointer to the first element of a row.
reverse_row_range rrow(size_type i)
Range of a row in reverse order.
iterator end()
Iterator to one pass the lower right corner of the matrix.
const_iterator cend() const
Iterator to one pass the lower right corner of the matrix.
col_range col(size_type i)
Range of a column.
Range< const_col_iterator > const_col_range
std::reverse_iterator< row_iterator > reverse_row_iterator
pointer row_data(size_type i)
Pointer to the first element of a row.
const_reverse_col_iterator col_rbegin(size_type j) const
Iterator to the end of a column.
const_col_iterator col_begin(size_type j) const
Iterator to the beginning of a column.
pointer col_data(size_type j)
Pointer to the beginning of a column.
row_iterator row_end(size_type i)
Iterator to one pass the end of a row.
static constexpr MatrixLayout layout()
The layout of the matrix.
size_type ldim() const
The number of elements in the leading dimension.
const_reverse_col_iterator col_crend(size_type j) const
Iterator to one before the beginning of a column.
size_type row_stride() const
The stride of row-wise access through row_data()
friend bool is_equal(const Matrix &m1, const Matrix &m2)
Compare equality.
void push_back_col(InputIter first)
Insert a new coloumn at the right.
reverse_iterator rend()
Iterator one before the upper left corner of the matrix.
const_row_iterator row_begin(size_type i) const
Iterator to the beginning of a row.
Matrix & operator=(Matrix &&other) noexcept(noexcept(data_.swap(other.data_)))
Move assignment operator.
pointer data()
Pointer to the upper left corner of the matrix.
Range< row_iterator > row_range
void shrink_to_fit()
Release memory no longer needed.
const_reverse_col_iterator col_crbegin(size_type j) const
Iterator to the end of a column.
const_reverse_col_range crcol(size_type i) const
Range of a column in reverse order.
const_reverse_row_range crrow(size_type i) const
Range of a row in reverse order.
std::reverse_iterator< iterator > reverse_iterator
Range< col_iterator > col_range
const_row_iterator row_cend(size_type i) const
Iterator to one pass the end of a row.
friend bool operator!=(const Matrix &m1, const Matrix &m2)
Compare inequality.
size_type size() const
The total number of elements.
iterator begin()
Iterator to the upper left corner of the matrix.
const_pointer col_data(size_type j) const
Pointer to the beginning of a column.
row_iterator row_begin(size_type i)
Iterator to the beginning of a row.
col_iterator col_begin(size_type i)
Iterator to the beginning of a column.
friend void swap(Matrix &m1, Matrix &m2) noexcept(noexcept(m1.swap(m2)))
Swap two matrices.
const_reverse_row_range rrow(size_type i) const
Range of a row in reverse order.
const_reverse_row_iterator row_crbegin(size_type i) const
Iterator to the end of a row.
const value_type * const_pointer
Range< reverse_col_iterator > reverse_col_range
std::conditional_t< Layout==ColMajor, const_pointer, StepIterator< const_pointer > > const_col_iterator
row_range row(size_type i)
Range of a row.
const_pointer data() const
Pointer to the upper left corner of the matrix.
Range< const_reverse_col_iterator > const_reverse_col_range
constexpr MatrixLayout ColMajor
std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const Matrix< T, Layout, Alloc > &mat)
Output operator.
reverse_row_iterator row_rend(size_type i)
Iterator to one before the beginning of a row.
const_col_iterator col_cbegin(size_type j) const
Iterator to the beginning of a column.
const_col_iterator col_cend(size_type j) const
Iterator to one pass the end of a column.
Iterator adapter which increment the base iterator in multiple steps.
Matrix(Matrix &&other) noexcept(std::is_nothrow_move_constructible< Vector< T, Alloc >>::value)
Move constructor.
void reserve(size_type n, size_type m)
Reserve storage space for the matrix.
Matrix< T, Layout==RowMajor ? ColMajor :RowMajor, Alloc > transpose_type
Standard library compatible allocator with policies.
const_reverse_row_iterator row_rbegin(size_type i) const
Iterator to the end of a row.
col_iterator col_end(size_type j)
Iterator to one pass the end of a column.
size_type col_stride() const
The stride size of column-wise access through col_data()
size_type nrow() const
The number of rows.
std::conditional_t< Layout==ColMajor, pointer, StepIterator< pointer > > col_iterator
reverse_col_range rcol(size_type i)
Range of a column in reverse order.
reverse_col_iterator col_rend(size_type j)
Iterator to one before the beginning of a column.
std::reverse_iterator< const_col_iterator > const_reverse_col_iterator
std::ptrdiff_t difference_type
const value_type & const_reference
void push_back_row(InputIter first)
Insert a new row at the bottom.
const_reverse_iterator crbegin() const
Iterator to the lower right corner of the matrix.
reference operator()(size_type i, size_type j)
Access an element in the matrix.
std::conditional_t< Layout==RowMajor, pointer, StepIterator< pointer > > row_iterator
const_pointer const_iterator
std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, Matrix< T, Layout, Alloc > &mat)
Input operator.
Matrix & operator=(const Matrix &)=default
Copy assignment operator.
reference at(size_type i, size_type j)
Access an element in the matrix with bound checking.
const_reverse_col_range rcol(size_type i) const
Range of a column in reverse order.
const_reverse_row_iterator row_crend(size_type i) const
Iterator to one before the beginning of a row.
reverse_iterator rbegin()
Iterator to the lower right corner of the matrix.
const_row_range crow(size_type i) const
Range of a row.
const_iterator cbegin() const
Iterator to the upper left corner of the matrix.
const_row_range row(size_type i) const
Range of a row.
MatrixLayout
Matrix layout.
const_reverse_row_iterator row_rend(size_type i) const
Iterator to one before the beginning of a row.