|
|
|
/*! @file
|
|
|
|
|
|
|
|
@id $Id$
|
|
|
|
*/
|
|
|
|
// 1 2 3 4 5 6 7 8
|
|
|
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cassert>
|
|
|
|
#include <type_traits>
|
|
|
|
|
|
|
|
template<typename TYPE, typename ARRAY=TYPE*> class MatrixBase {
|
|
|
|
|
|
|
|
//..............................................................constants
|
|
|
|
public:
|
|
|
|
|
|
|
|
const size_t ROWS;
|
|
|
|
const size_t COLUMNS;
|
|
|
|
const size_t SIZE;
|
|
|
|
const size_t MEM_SIZE;
|
|
|
|
|
|
|
|
//...............................................................typedefs
|
|
|
|
public:
|
|
|
|
|
|
|
|
/// @name Auxiliary Classes
|
|
|
|
///{
|
|
|
|
|
|
|
|
/// Return One Row as Vector, internally used for element access
|
|
|
|
/** Only used to access values:
|
|
|
|
|
|
|
|
@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 MatrixBase;
|
|
|
|
RowVector() = delete; // forbidden
|
|
|
|
RowVector(const MatrixBase& m, TYPE c[]): _m(m), _v(c) {}
|
|
|
|
const MatrixBase& _m;
|
|
|
|
TYPE *_v;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Same as RowVector, but in a constant environment.
|
|
|
|
class ConstRowVector {
|
|
|
|
public:
|
|
|
|
const TYPE& operator[](size_t column) const {
|
|
|
|
assert(column<_m.COLUMNS);
|
|
|
|
return _v[column];
|
|
|
|
}
|
|
|
|
protected:
|
|
|
|
friend class MatrixBase;
|
|
|
|
ConstRowVector() = delete; // forbidden
|
|
|
|
ConstRowVector(const MatrixBase& m, const TYPE c[]): _m(m), _v(c) {}
|
|
|
|
const MatrixBase& _m;
|
|
|
|
const TYPE *_v;
|
|
|
|
};
|
|
|
|
|
|
|
|
///}
|
|
|
|
|
|
|
|
//................................................................methods
|
|
|
|
public:
|
|
|
|
|
|
|
|
/// @name construction
|
|
|
|
///{
|
|
|
|
|
|
|
|
MatrixBase(size_t rows, size_t columns):
|
|
|
|
ROWS(rows), COLUMNS(columns),
|
|
|
|
SIZE(ROWS*COLUMNS), MEM_SIZE(SIZE*sizeof(TYPE)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...ARGS>
|
|
|
|
MatrixBase(size_t rows, size_t columns, ARGS...t):
|
|
|
|
ROWS(rows), COLUMNS(columns),
|
|
|
|
SIZE(ROWS*COLUMNS), MEM_SIZE(SIZE*sizeof(TYPE)),
|
|
|
|
_c{std::forward<TYPE>(t)...} {
|
|
|
|
}
|
|
|
|
|
|
|
|
///}
|
|
|
|
|
|
|
|
/// @name operators
|
|
|
|
///{
|
|
|
|
|
|
|
|
MatrixBase& operator=(TYPE oc[]) {
|
|
|
|
assert(sizeof(oc)==MEM_SIZE);
|
|
|
|
memcpy(_c, oc, MEM_SIZE);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
MatrixBase& operator=(const MatrixBase& o) {
|
|
|
|
assert_check(o);
|
|
|
|
memcpy(_c, o._c, MEM_SIZE);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const MatrixBase& o) const {
|
|
|
|
if (!check(o)) 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 MatrixBase& o) const {
|
|
|
|
return !operator==(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
MatrixBase& operator+=(const MatrixBase& o) {
|
|
|
|
assert_check(o);
|
|
|
|
TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE);
|
|
|
|
while (to>(TYPE*)(_c)) *--to += *--from;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
MatrixBase& operator-=(const MatrixBase& o) {
|
|
|
|
assert_check(o);
|
|
|
|
TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE);
|
|
|
|
while (to>(TYPE*)(_c)) *--to -= *--from;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
MatrixBase& operator*=(const TYPE& o) {
|
|
|
|
TYPE *res((TYPE*)(_c)+SIZE);
|
|
|
|
while (res>(TYPE*)(_c)) *--res *= o;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
MatrixBase& operator/=(const TYPE& o) {
|
|
|
|
TYPE *res((TYPE*)(_c)+SIZE);
|
|
|
|
while (res>(TYPE*)(_c)) *--res /= o;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
///}
|
|
|
|
|
|
|
|
/// @name element access
|
|
|
|
///{
|
|
|
|
|
|
|
|
TYPE& operator()(size_t row, size_t column) {
|
|
|
|
assert(row<ROWS);
|
|
|
|
assert(column<COLUMNS);
|
|
|
|
return *((TYPE*)_c+row*COLUMNS+column);
|
|
|
|
}
|
|
|
|
|
|
|
|
const TYPE& operator()(size_t row, size_t column) const {
|
|
|
|
assert(row<ROWS);
|
|
|
|
assert(column<COLUMNS);
|
|
|
|
return *((TYPE*)_c+row*COLUMNS+column);
|
|
|
|
}
|
|
|
|
|
|
|
|
RowVector operator[](size_t row) {
|
|
|
|
assert(row<ROWS);
|
|
|
|
return RowVector(*this, (TYPE*)_c+row*COLUMNS);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ConstRowVector operator[](size_t row) const {
|
|
|
|
assert(row<ROWS);
|
|
|
|
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
|
|
|
|
protected:
|
|
|
|
|
|
|
|
ARRAY _c;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
|
|
|
template<typename TYPE, size_t TROWS=0, size_t TCOLUMNS=0> class Matrix:
|
|
|
|
public MatrixBase<TYPE, TYPE[TROWS][TCOLUMNS]> {
|
|
|
|
|
|
|
|
//...............................................................typedefs
|
|
|
|
private:
|
|
|
|
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
|
|
|
Matrix(const Matrix& o): Matrix() {
|
|
|
|
memcpy(Parent::_c, o._c, Parent::MEM_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
///}
|
|
|
|
|
|
|
|
/// @name operators
|
|
|
|
///{
|
|
|
|
|
|
|
|
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<size_t NEWCOLUMNS>
|
|
|
|
Matrix operator*(const Matrix<TYPE, TCOLUMNS, NEWCOLUMNS>& o) {
|
|
|
|
Matrix<TYPE, TROWS, NEWCOLUMNS> res;
|
|
|
|
for (size_t i(0); i<TROWS; ++i)
|
|
|
|
for (size_t k(0); k<NEWCOLUMNS; ++k)
|
|
|
|
for (size_t j(0); j<TCOLUMNS; ++j)
|
|
|
|
res(i, k) += (*this)(i, j) * o(j, k);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
|
|
|
template<typename TYPE> class Matrix<TYPE, 0, 0>: public MatrixBase<TYPE> {
|
|
|
|
|
|
|
|
//...............................................................typedefs
|
|
|
|
private:
|
|
|
|
|
|
|
|
typedef MatrixBase<TYPE> Parent;
|
|
|
|
|
|
|
|
//................................................................methods
|
|
|
|
public:
|
|
|
|
|
|
|
|
/// @name construction
|
|
|
|
///{
|
|
|
|
|
|
|
|
Matrix(size_t rows, size_t columns):
|
|
|
|
Parent(rows, columns) {
|
|
|
|
Parent::_c = new TYPE[rows*columns];
|
|
|
|
memset(Parent::_c, 0, Parent::MEM_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...ARGS>
|
|
|
|
Matrix(size_t rows, size_t columns, ARGS...t):
|
|
|
|
Matrix(rows, columns) {
|
|
|
|
assert(sizeof...(t)==Parent::SIZE);
|
|
|
|
copy_args(Parent::_c, t...);
|
|
|
|
}
|
|
|
|
|
|
|
|
Matrix(const Matrix& o): Matrix(o.ROWS, o.Parent::COLUMNS) {
|
|
|
|
memcpy(Parent::_c, o.Parent::_c, Parent::MEM_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
///}
|
|
|
|
|
|
|
|
/// @name destruction
|
|
|
|
///{
|
|
|
|
|
|
|
|
virtual ~Matrix() {
|
|
|
|
delete[] Parent::_c;
|
|
|
|
}
|
|
|
|
|
|
|
|
///}
|
|
|
|
|
|
|
|
/// @name operators
|
|
|
|
///{
|
|
|
|
|
|
|
|
Matrix& operator=(const Matrix& o) {
|
|
|
|
if (o.ROWS!=Parent::ROWS&&o.COLUMNS!=Parent::COLUMNS) {
|
|
|
|
delete[] Parent::_c;
|
|
|
|
Parent::ROWS = o.ROWS;
|
|
|
|
Parent::COLUMNS = o.COLUMNS;
|
|
|
|
Parent::SIZE = o.SIZE;
|
|
|
|
Parent::MEM_SIZE = o.MEM_SIZE;
|
|
|
|
Parent::_c = new TYPE[Parent::SIZE];
|
|
|
|
}
|
|
|
|
return Parent::operator=(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
Matrix T() const {
|
|
|
|
Matrix res(Parent::COLUMNS, Parent::ROWS);
|
|
|
|
for (size_t row(0); row<Parent::ROWS; ++row)
|
|
|
|
for (size_t column(0); column<Parent::COLUMNS; ++column)
|
|
|
|
res(column, row) = Parent::operator()(row, column);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
Matrix operator-() const {
|
|
|
|
Matrix res(Parent::COLUMNS, Parent::ROWS);
|
|
|
|
for (TYPE *to((TYPE*)(res._c)+Parent::SIZE); to>(TYPE*)(Parent::_c); --to)
|
|
|
|
*to = -*to;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
///}
|
|
|
|
|
|
|
|
//................................................................methods
|
|
|
|
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*) {}
|
|
|
|
template<typename ...ARGS>
|
|
|
|
void copy_args(TYPE* to, TYPE t1, ARGS...t) {
|
|
|
|
*to = t1;
|
|
|
|
copy_args(++to, t...);
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
|
|
|
template<typename TYPE, size_t ROWS, size_t COLUMNS>
|
|
|
|
std::ostream& operator<<(std::ostream& s, const Matrix<TYPE, ROWS, COLUMNS>& m) {
|
|
|
|
for (size_t w = 0; w < m.ROWS; ++w) {
|
|
|
|
for (size_t h = 0; h < m.COLUMNS;++h) {
|
|
|
|
s<<m[w][h]<<' ';
|
|
|
|
}
|
|
|
|
s<<'\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|