|
|
@ -10,15 +10,15 @@ |
|
|
|
#include <cassert> |
|
|
|
#include <cassert> |
|
|
|
#include <type_traits> |
|
|
|
#include <type_traits> |
|
|
|
|
|
|
|
|
|
|
|
template<typename TYPE, size_t TROWS=0, size_t TCOLUMNS=0> class Matrix { |
|
|
|
template<typename TYPE, typename ARRAY=TYPE*> class MatrixBase { |
|
|
|
|
|
|
|
|
|
|
|
//........................................................const.variables
|
|
|
|
//..............................................................constants
|
|
|
|
public: |
|
|
|
public: |
|
|
|
|
|
|
|
|
|
|
|
static const size_t ROWS = TROWS; |
|
|
|
const size_t ROWS; |
|
|
|
static const size_t COLUMNS = TCOLUMNS; |
|
|
|
const size_t COLUMNS; |
|
|
|
static const size_t SIZE = ROWS*COLUMNS; |
|
|
|
const size_t SIZE; |
|
|
|
static const size_t MEM_SIZE = ROWS*COLUMNS*sizeof(TYPE); |
|
|
|
const size_t MEM_SIZE; |
|
|
|
|
|
|
|
|
|
|
|
//...............................................................typedefs
|
|
|
|
//...............................................................typedefs
|
|
|
|
public:
|
|
|
|
public:
|
|
|
@ -36,12 +36,14 @@ template<typename TYPE, size_t TROWS=0, size_t TCOLUMNS=0> class Matrix { |
|
|
|
class RowVector { |
|
|
|
class RowVector { |
|
|
|
public: |
|
|
|
public: |
|
|
|
TYPE& operator[](size_t column) { |
|
|
|
TYPE& operator[](size_t column) { |
|
|
|
|
|
|
|
assert(column<_m.COLUMNS); |
|
|
|
return _v[column]; |
|
|
|
return _v[column]; |
|
|
|
} |
|
|
|
} |
|
|
|
protected: |
|
|
|
protected: |
|
|
|
friend class Matrix; |
|
|
|
friend class MatrixBase; |
|
|
|
RowVector() = delete; // forbidden
|
|
|
|
RowVector() = delete; // forbidden
|
|
|
|
RowVector(TYPE c[COLUMNS]): _v(c) {} |
|
|
|
RowVector(const MatrixBase& m, TYPE c[]): _m(m), _v(c) {} |
|
|
|
|
|
|
|
const MatrixBase& _m; |
|
|
|
TYPE *_v; |
|
|
|
TYPE *_v; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -49,12 +51,14 @@ template<typename TYPE, size_t TROWS=0, size_t TCOLUMNS=0> class Matrix { |
|
|
|
class ConstRowVector { |
|
|
|
class ConstRowVector { |
|
|
|
public: |
|
|
|
public: |
|
|
|
const TYPE& operator[](size_t column) const { |
|
|
|
const TYPE& operator[](size_t column) const { |
|
|
|
|
|
|
|
assert(column<_m.COLUMNS); |
|
|
|
return _v[column]; |
|
|
|
return _v[column]; |
|
|
|
} |
|
|
|
} |
|
|
|
protected: |
|
|
|
protected: |
|
|
|
friend class Matrix; |
|
|
|
friend class MatrixBase; |
|
|
|
ConstRowVector() = delete; // forbidden
|
|
|
|
ConstRowVector() = delete; // forbidden
|
|
|
|
ConstRowVector(const TYPE c[COLUMNS]): _v(c) {} |
|
|
|
ConstRowVector(const MatrixBase& m, const TYPE c[]): _m(m), _v(c) {} |
|
|
|
|
|
|
|
const MatrixBase& _m; |
|
|
|
const TYPE *_v; |
|
|
|
const TYPE *_v; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -66,17 +70,16 @@ template<typename TYPE, size_t TROWS=0, size_t TCOLUMNS=0> class Matrix { |
|
|
|
/// @name construction
|
|
|
|
/// @name construction
|
|
|
|
///{
|
|
|
|
///{
|
|
|
|
|
|
|
|
|
|
|
|
Matrix() { |
|
|
|
MatrixBase(size_t rows, size_t columns): |
|
|
|
memset(_c, 0, MEM_SIZE); |
|
|
|
ROWS(rows), COLUMNS(columns), |
|
|
|
|
|
|
|
SIZE(ROWS*COLUMNS), MEM_SIZE(SIZE*sizeof(TYPE)) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<typename ...ARGS> |
|
|
|
template<typename ...ARGS> |
|
|
|
Matrix(ARGS...t): _c{std::forward<TYPE>(t)...} { |
|
|
|
MatrixBase(size_t rows, size_t columns, ARGS...t): |
|
|
|
static_assert(sizeof...(t)==SIZE, "variadic matrix initialisation requires correct array size"); |
|
|
|
ROWS(rows), COLUMNS(columns), |
|
|
|
} |
|
|
|
SIZE(ROWS*COLUMNS), MEM_SIZE(SIZE*sizeof(TYPE)), |
|
|
|
|
|
|
|
_c{std::forward<TYPE>(t)...} { |
|
|
|
Matrix(const Matrix& o) { |
|
|
|
|
|
|
|
memcpy(_c, o._c, MEM_SIZE); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
///}
|
|
|
|
///}
|
|
|
@ -84,47 +87,38 @@ template<typename TYPE, size_t TROWS=0, size_t TCOLUMNS=0> class Matrix { |
|
|
|
/// @name operators
|
|
|
|
/// @name operators
|
|
|
|
///{
|
|
|
|
///{
|
|
|
|
|
|
|
|
|
|
|
|
Matrix& operator=(TYPE oc[ROWS][COLUMNS]) { |
|
|
|
MatrixBase& operator=(TYPE oc[]) { |
|
|
|
|
|
|
|
assert(sizeof(oc)==MEM_SIZE); |
|
|
|
memcpy(_c, oc, MEM_SIZE); |
|
|
|
memcpy(_c, oc, MEM_SIZE); |
|
|
|
return *this; |
|
|
|
return *this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Matrix& operator=(const Matrix& o) { |
|
|
|
MatrixBase& operator=(const MatrixBase& o) { |
|
|
|
|
|
|
|
assert_check(o); |
|
|
|
memcpy(_c, o._c, MEM_SIZE); |
|
|
|
memcpy(_c, o._c, MEM_SIZE); |
|
|
|
return *this; |
|
|
|
return *this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool operator==(const Matrix& o) const { |
|
|
|
bool operator==(const MatrixBase& o) const { |
|
|
|
|
|
|
|
if (!check(o)) return false; |
|
|
|
TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE); |
|
|
|
TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE); |
|
|
|
while (to>(TYPE*)(_c)) if (*--to != *--from) return false; |
|
|
|
while (to>(TYPE*)(_c)) if (*--to != *--from) return false; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool operator!=(const Matrix& o) const { |
|
|
|
bool operator!=(const MatrixBase& o) const { |
|
|
|
return !operator==(o); |
|
|
|
return !operator==(o); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Matrix<TYPE, COLUMNS, ROWS> T() const { |
|
|
|
MatrixBase& operator+=(const MatrixBase& o) { |
|
|
|
Matrix<TYPE, COLUMNS, ROWS> res; |
|
|
|
assert_check(o); |
|
|
|
for (size_t row(0); row<ROWS; ++row) |
|
|
|
|
|
|
|
for (size_t column(0); column<COLUMNS; ++column) |
|
|
|
|
|
|
|
res(column, row) = operator()(row, column); |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Matrix operator-() const { |
|
|
|
|
|
|
|
Matrix res; |
|
|
|
|
|
|
|
for (TYPE *to((TYPE*)(res._c)+SIZE); to>(TYPE*)(_c); --to) *to = -*to; |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Matrix& operator+=(const Matrix& o) { |
|
|
|
|
|
|
|
TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE); |
|
|
|
TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE); |
|
|
|
while (to>(TYPE*)(_c)) *--to += *--from; |
|
|
|
while (to>(TYPE*)(_c)) *--to += *--from; |
|
|
|
return *this; |
|
|
|
return *this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Matrix& operator-=(const Matrix& o) { |
|
|
|
MatrixBase& operator-=(const MatrixBase& o) { |
|
|
|
|
|
|
|
assert_check(o); |
|
|
|
TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE); |
|
|
|
TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE); |
|
|
|
while (to>(TYPE*)(_c)) *--to -= *--from; |
|
|
|
while (to>(TYPE*)(_c)) *--to -= *--from; |
|
|
|
return *this; |
|
|
|
return *this; |
|
|
@ -134,116 +128,131 @@ template<typename TYPE, size_t TROWS=0, size_t TCOLUMNS=0> class Matrix { |
|
|
|
|
|
|
|
|
|
|
|
/// @name element access
|
|
|
|
/// @name element access
|
|
|
|
///{
|
|
|
|
///{
|
|
|
|
|
|
|
|
|
|
|
|
TYPE& operator()(size_t row, size_t column) { |
|
|
|
TYPE& operator()(size_t row, size_t column) { |
|
|
|
assert(row<ROWS); |
|
|
|
assert(row<ROWS); |
|
|
|
assert(column<COLUMNS); |
|
|
|
assert(column<COLUMNS); |
|
|
|
return _c[row][column]; |
|
|
|
return *((TYPE*)_c+row*COLUMNS+column); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const TYPE& operator()(size_t row, size_t column) const { |
|
|
|
const TYPE& operator()(size_t row, size_t column) const { |
|
|
|
assert(row<ROWS); |
|
|
|
assert(row<ROWS); |
|
|
|
assert(column<COLUMNS); |
|
|
|
assert(column<COLUMNS); |
|
|
|
return _c[row][column]; |
|
|
|
return *((TYPE*)_c+row*COLUMNS+column); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
RowVector operator[](size_t row) { |
|
|
|
RowVector operator[](size_t row) { |
|
|
|
assert(row<ROWS); |
|
|
|
assert(row<ROWS); |
|
|
|
return RowVector(_c[row]); |
|
|
|
return RowVector(*this, (TYPE*)_c+row*COLUMNS); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const ConstRowVector operator[](size_t row) const { |
|
|
|
const ConstRowVector operator[](size_t row) const { |
|
|
|
assert(row<ROWS); |
|
|
|
assert(row<ROWS); |
|
|
|
return ConstRowVector(_c[row]); |
|
|
|
return ConstRowVector(*this, (TYPE*)_c+row*COLUMNS); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
///}
|
|
|
|
///}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//................................................................methods
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void assert_check(const MatrixBase& o) const {} |
|
|
|
|
|
|
|
virtual bool check(const MatrixBase& o) const { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//..............................................................variables
|
|
|
|
//..............................................................variables
|
|
|
|
protected: |
|
|
|
protected: |
|
|
|
|
|
|
|
|
|
|
|
TYPE _c[ROWS][COLUMNS]; |
|
|
|
ARRAY _c; |
|
|
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename TYPE> class Matrix<TYPE, 0, 0> { |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
//..............................................................constants
|
|
|
|
//==============================================================================
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const size_t ROWS; |
|
|
|
template<typename TYPE, size_t TROWS=0, size_t TCOLUMNS=0> class Matrix: |
|
|
|
const size_t COLUMNS; |
|
|
|
public MatrixBase<TYPE, TYPE[TROWS][TCOLUMNS]> { |
|
|
|
const size_t SIZE; |
|
|
|
|
|
|
|
const size_t MEM_SIZE; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//...............................................................typedefs
|
|
|
|
//...............................................................typedefs
|
|
|
|
public:
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
|
|
/// @name Auxiliary Classes
|
|
|
|
typedef MatrixBase<TYPE, TYPE[TROWS][TCOLUMNS]> Parent; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//................................................................methods
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @name construction
|
|
|
|
///{
|
|
|
|
///{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Matrix(): Parent(TROWS, TCOLUMNS) {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename ...ARGS> |
|
|
|
|
|
|
|
Matrix(ARGS...t): Parent(TROWS, TCOLUMNS, t...) { |
|
|
|
|
|
|
|
static_assert(sizeof...(t)==TROWS*TCOLUMNS, |
|
|
|
|
|
|
|
"wrong array size"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Return One Row as Vector, internally used for element access
|
|
|
|
Matrix(const Matrix& o): Matrix() { |
|
|
|
/** Only used to access values:
|
|
|
|
memcpy(Parent::_c, o._c, Parent::MEM_SIZE); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@code |
|
|
|
///}
|
|
|
|
Matrix<int,4,4> m; |
|
|
|
|
|
|
|
m[2][2] = 1; |
|
|
|
|
|
|
|
@endcode */ |
|
|
|
|
|
|
|
class RowVector { |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
TYPE& operator[](size_t column) { |
|
|
|
|
|
|
|
assert(column<_m.COLUMNS); |
|
|
|
|
|
|
|
return _v[column]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
|
|
friend class Matrix; |
|
|
|
|
|
|
|
RowVector() = delete; // forbidden
|
|
|
|
|
|
|
|
RowVector(const Matrix& m, TYPE c[]): _m(m), _v(c) {} |
|
|
|
|
|
|
|
const Matrix& _m; |
|
|
|
|
|
|
|
TYPE *_v; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Same as RowVector, but in a constant environment.
|
|
|
|
/// @name operators
|
|
|
|
class ConstRowVector { |
|
|
|
///{
|
|
|
|
public: |
|
|
|
|
|
|
|
const TYPE& operator[](size_t column) const { |
|
|
|
|
|
|
|
assert(column<_m.COLUMNS); |
|
|
|
|
|
|
|
return _v[column]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
|
|
friend class Matrix; |
|
|
|
|
|
|
|
ConstRowVector() = delete; // forbidden
|
|
|
|
|
|
|
|
ConstRowVector(const Matrix& m, const TYPE c[]): _m(m), _v(c) {} |
|
|
|
|
|
|
|
const Matrix& _m; |
|
|
|
|
|
|
|
const TYPE *_v; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///}
|
|
|
|
Matrix& operator=(TYPE oc[TROWS][TCOLUMNS]) { |
|
|
|
|
|
|
|
memcpy(Parent::_c, oc, Parent::MEM_SIZE); |
|
|
|
|
|
|
|
return *this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Matrix<TYPE, TCOLUMNS, TROWS> T() const { |
|
|
|
|
|
|
|
Matrix<TYPE, TCOLUMNS, TROWS> res; |
|
|
|
|
|
|
|
for (size_t row(0); row<TROWS; ++row) |
|
|
|
|
|
|
|
for (size_t column(0); column<TCOLUMNS; ++column) |
|
|
|
|
|
|
|
res(column, row) = Parent::operator()(row, column); |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Matrix operator-() const { |
|
|
|
|
|
|
|
Matrix res; |
|
|
|
|
|
|
|
for (TYPE *to((TYPE*)(res._c)+Parent::SIZE); to>(TYPE*)(Parent::_c); --to) |
|
|
|
|
|
|
|
*to = -*to; |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename TYPE> class Matrix<TYPE, 0, 0>: public MatrixBase<TYPE> { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//...............................................................typedefs
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef MatrixBase<TYPE> Parent; |
|
|
|
|
|
|
|
|
|
|
|
//................................................................methods
|
|
|
|
//................................................................methods
|
|
|
|
public: |
|
|
|
public: |
|
|
|
|
|
|
|
|
|
|
|
/// @name construction
|
|
|
|
/// @name construction
|
|
|
|
///{
|
|
|
|
///{
|
|
|
|
|
|
|
|
|
|
|
|
Matrix(size_t rows, size_t columns): |
|
|
|
Matrix(size_t rows, size_t columns): |
|
|
|
ROWS(rows), |
|
|
|
Parent(rows, columns) { |
|
|
|
COLUMNS(columns), |
|
|
|
Parent::_c = new TYPE[rows*columns]; |
|
|
|
SIZE(rows*columns), |
|
|
|
memset(Parent::_c, 0, Parent::MEM_SIZE); |
|
|
|
MEM_SIZE(rows*columns*sizeof(TYPE)), |
|
|
|
|
|
|
|
_c(new TYPE[rows*columns]) { |
|
|
|
|
|
|
|
memset(_c, 0, MEM_SIZE); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<typename ...ARGS> |
|
|
|
template<typename ...ARGS> |
|
|
|
Matrix(size_t rows, size_t columns, ARGS...t): |
|
|
|
Matrix(size_t rows, size_t columns, ARGS...t): |
|
|
|
Matrix(rows, columns) { |
|
|
|
Matrix(rows, columns) { |
|
|
|
assert(sizeof...(t)==SIZE); |
|
|
|
assert(sizeof...(t)==Parent::SIZE); |
|
|
|
copy_args(_c, t...); |
|
|
|
copy_args(Parent::_c, t...); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Matrix(const Matrix& o): Matrix(o.ROWS, o.COLUMNS) { |
|
|
|
Matrix(const Matrix& o): Matrix(o.ROWS, o.Parent::COLUMNS) { |
|
|
|
memcpy(_c, o._c, MEM_SIZE); |
|
|
|
memcpy(Parent::_c, o.Parent::_c, Parent::MEM_SIZE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
///}
|
|
|
|
///}
|
|
|
@ -251,107 +260,56 @@ template<typename TYPE> class Matrix<TYPE, 0, 0> { |
|
|
|
/// @name destruction
|
|
|
|
/// @name destruction
|
|
|
|
///{
|
|
|
|
///{
|
|
|
|
|
|
|
|
|
|
|
|
~Matrix() { |
|
|
|
virtual ~Matrix() { |
|
|
|
delete[] _c; |
|
|
|
delete[] Parent::_c; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
///}
|
|
|
|
///}
|
|
|
|
|
|
|
|
|
|
|
|
/// @name operators
|
|
|
|
/// @name operators
|
|
|
|
///{
|
|
|
|
///{
|
|
|
|
|
|
|
|
|
|
|
|
Matrix& operator=(TYPE oc[]) { |
|
|
|
|
|
|
|
assert(sizeof(oc)==MEM_SIZE); |
|
|
|
|
|
|
|
memcpy(_c, oc, MEM_SIZE); |
|
|
|
|
|
|
|
return *this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Matrix& operator=(const Matrix& o) { |
|
|
|
Matrix& operator=(const Matrix& o) { |
|
|
|
if (o.ROWS!=ROWS&&o.COLUMNS!=COLUMNS) { |
|
|
|
if (o.ROWS!=Parent::ROWS&&o.COLUMNS!=Parent::COLUMNS) { |
|
|
|
delete[] _c; |
|
|
|
delete[] Parent::_c; |
|
|
|
ROWS = o.ROWS; |
|
|
|
Parent::ROWS = o.ROWS; |
|
|
|
COLUMNS = o.COLUMNS; |
|
|
|
Parent::COLUMNS = o.COLUMNS; |
|
|
|
SIZE = o.SIZE; |
|
|
|
Parent::SIZE = o.SIZE; |
|
|
|
MEM_SIZE = o.MEM_SIZE; |
|
|
|
Parent::MEM_SIZE = o.MEM_SIZE; |
|
|
|
_c = new TYPE[SIZE]; |
|
|
|
Parent::_c = new TYPE[Parent::SIZE]; |
|
|
|
} |
|
|
|
} |
|
|
|
memcpy(_c, o._c, MEM_SIZE); |
|
|
|
return Parent::operator=(o); |
|
|
|
return *this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool operator==(const Matrix& o) const { |
|
|
|
|
|
|
|
if (o.ROWS!=ROWS||o.COLUMNS!=COLUMNS) return false; |
|
|
|
|
|
|
|
TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE); |
|
|
|
|
|
|
|
while (to>(TYPE*)(_c)) if (*--to != *--from) return false; |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool operator!=(const Matrix& o) const { |
|
|
|
|
|
|
|
return !operator==(o); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Matrix T() const { |
|
|
|
Matrix T() const { |
|
|
|
Matrix res(COLUMNS, ROWS); |
|
|
|
Matrix res(Parent::COLUMNS, Parent::ROWS); |
|
|
|
for (size_t row(0); row<ROWS; ++row) |
|
|
|
for (size_t row(0); row<Parent::ROWS; ++row) |
|
|
|
for (size_t column(0); column<COLUMNS; ++column) |
|
|
|
for (size_t column(0); column<Parent::COLUMNS; ++column) |
|
|
|
res(column, row) = operator()(row, column); |
|
|
|
res(column, row) = Parent::operator()(row, column); |
|
|
|
return res; |
|
|
|
return res; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Matrix operator-() const { |
|
|
|
Matrix operator-() const { |
|
|
|
Matrix res(COLUMNS, ROWS); |
|
|
|
Matrix res(Parent::COLUMNS, Parent::ROWS); |
|
|
|
for (TYPE *to((TYPE*)(res._c)+SIZE); to>(TYPE*)(_c); --to) *to = -*to; |
|
|
|
for (TYPE *to((TYPE*)(res._c)+Parent::SIZE); to>(TYPE*)(Parent::_c); --to) |
|
|
|
|
|
|
|
*to = -*to; |
|
|
|
return res; |
|
|
|
return res; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Matrix& operator+=(const Matrix& o) { |
|
|
|
|
|
|
|
assert(o.ROWS==ROWS); |
|
|
|
|
|
|
|
assert(o.COLUMNS==COLUMNS); |
|
|
|
|
|
|
|
TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE); |
|
|
|
|
|
|
|
while (to>(TYPE*)(_c)) *--to += *--from; |
|
|
|
|
|
|
|
return *this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Matrix& operator-=(const Matrix& o) { |
|
|
|
|
|
|
|
assert(o.ROWS==ROWS); |
|
|
|
|
|
|
|
assert(o.COLUMNS==COLUMNS); |
|
|
|
|
|
|
|
TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE); |
|
|
|
|
|
|
|
while (to>(TYPE*)(_c)) *--to -= *--from; |
|
|
|
|
|
|
|
return *this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @name element access
|
|
|
|
|
|
|
|
///{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TYPE& operator()(size_t row, size_t column) { |
|
|
|
|
|
|
|
assert(row<ROWS); |
|
|
|
|
|
|
|
assert(column<COLUMNS); |
|
|
|
|
|
|
|
return *(_c+row*COLUMNS+column); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const TYPE& operator()(size_t row, size_t column) const { |
|
|
|
|
|
|
|
assert(row<ROWS); |
|
|
|
|
|
|
|
assert(column<COLUMNS); |
|
|
|
|
|
|
|
return *(_c+row*COLUMNS+column); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RowVector operator[](size_t row) { |
|
|
|
|
|
|
|
assert(row<ROWS); |
|
|
|
|
|
|
|
return RowVector(*this, _c+row*COLUMNS); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const ConstRowVector operator[](size_t row) const { |
|
|
|
|
|
|
|
assert(row<ROWS); |
|
|
|
|
|
|
|
return ConstRowVector(*this, _c+row*COLUMNS); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///}
|
|
|
|
///}
|
|
|
|
|
|
|
|
|
|
|
|
//................................................................methods
|
|
|
|
//................................................................methods
|
|
|
|
protected: |
|
|
|
protected: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void assert_check(const Matrix& o) const { |
|
|
|
|
|
|
|
assert(o.ROWS==Parent::ROWS); |
|
|
|
|
|
|
|
assert(o.COLUMNS==Parent::COLUMNS); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual bool check(const Matrix& o) const { |
|
|
|
|
|
|
|
return o.ROWS==Parent::ROWS && o.COLUMNS==Parent::COLUMNS; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void copy_args(TYPE*) {} |
|
|
|
void copy_args(TYPE*) {} |
|
|
|
template<typename ...ARGS> |
|
|
|
template<typename ...ARGS> |
|
|
|
void copy_args(TYPE* to, TYPE t1, ARGS...t) { |
|
|
|
void copy_args(TYPE* to, TYPE t1, ARGS...t) { |
|
|
@ -359,13 +317,10 @@ template<typename TYPE> class Matrix<TYPE, 0, 0> { |
|
|
|
copy_args(++to, t...); |
|
|
|
copy_args(++to, t...); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//..............................................................variables
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TYPE* _c; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
template<typename TYPE, size_t ROWS, size_t COLUMNS> |
|
|
|
template<typename TYPE, size_t ROWS, size_t COLUMNS> |
|
|
|
Matrix<TYPE, ROWS, COLUMNS> operator+(const Matrix<TYPE, ROWS, COLUMNS>& m1, const Matrix<TYPE, ROWS, COLUMNS>& m2) { |
|
|
|
Matrix<TYPE, ROWS, COLUMNS> operator+(const Matrix<TYPE, ROWS, COLUMNS>& m1, const Matrix<TYPE, ROWS, COLUMNS>& m2) { |
|
|
|
Matrix<TYPE, ROWS, COLUMNS> res(m1); |
|
|
|
Matrix<TYPE, ROWS, COLUMNS> res(m1); |
|
|
|