C++ matrix template classe for mathematics.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

384 lines
9.3 KiB

/*! @file
@id $Id$
*/
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
#include <iostream>
#include <cstring>
#include <cassert>
#include <type_traits>
template<typename TYPE, size_t TROWS=0, size_t TCOLUMNS=0> class Matrix {
//........................................................const.variables
public:
static const size_t ROWS = TROWS;
static const size_t COLUMNS = TCOLUMNS;
static const size_t SIZE = ROWS*COLUMNS;
static const size_t MEM_SIZE = ROWS*COLUMNS*sizeof(TYPE);
//...............................................................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) {
return _v[column];
}
protected:
friend class Matrix;
RowVector() = delete; // forbidden
RowVector(TYPE c[COLUMNS]): _v(c) {}
TYPE *_v;
};
/// Same as RowVector, but in a constant environment.
class ConstRowVector {
public:
const TYPE& operator[](size_t column) const {
return _v[column];
}
protected:
friend class Matrix;
ConstRowVector() = delete; // forbidden
ConstRowVector(const TYPE c[COLUMNS]): _v(c) {}
const TYPE *_v;
};
///}
//................................................................methods
public:
/// @name construction
///{
Matrix() {
memset(_c, 0, MEM_SIZE);
}
template<typename ...ARGS>
Matrix(ARGS...t): _c{std::forward<TYPE>(t)...} {
static_assert(sizeof...(t)==SIZE, "variadic matrix initialisation requires correct array size");
}
Matrix(const Matrix& o) {
memcpy(_c, o._c, MEM_SIZE);
}
///}
/// @name operators
///{
Matrix& operator=(TYPE oc[ROWS][COLUMNS]) {
memcpy(_c, oc, MEM_SIZE);
return *this;
}
Matrix& operator=(const Matrix& o) {
memcpy(_c, o._c, MEM_SIZE);
return *this;
}
bool operator==(const Matrix& o) const {
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<TYPE, COLUMNS, ROWS> T() const {
Matrix<TYPE, COLUMNS, ROWS> res;
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);
while (to>(TYPE*)(_c)) *--to += *--from;
return *this;
}
Matrix& operator-=(const Matrix& o) {
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][column];
}
const TYPE& operator()(size_t row, size_t column) const {
assert(row<ROWS);
assert(column<COLUMNS);
return _c[row][column];
}
RowVector operator[](size_t row) {
assert(row<ROWS);
return RowVector(_c[row]);
}
const ConstRowVector operator[](size_t row) const {
assert(row<ROWS);
return ConstRowVector(_c[row]);
}
///}
//..............................................................variables
protected:
TYPE _c[ROWS][COLUMNS];
};
template<typename TYPE> class Matrix<TYPE, 0, 0> {
//..............................................................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 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.
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;
};
///}
//................................................................methods
public:
/// @name construction
///{
Matrix(size_t rows, size_t columns):
ROWS(rows),
COLUMNS(columns),
SIZE(rows*columns),
MEM_SIZE(rows*columns*sizeof(TYPE)),
_c(new TYPE[rows*columns]) {
memset(_c, 0, MEM_SIZE);
}
template<typename ...ARGS>
Matrix(size_t rows, size_t columns, ARGS...t):
Matrix(rows, columns) {
assert(sizeof...(t)==SIZE);
copy_args(_c, t...);
}
Matrix(const Matrix& o): Matrix(o.ROWS, o.COLUMNS) {
memcpy(_c, o._c, MEM_SIZE);
}
///}
/// @name destruction
///{
~Matrix() {
delete[] _c;
}
///}
/// @name operators
///{
Matrix& operator=(TYPE oc[]) {
assert(sizeof(oc)==MEM_SIZE);
memcpy(_c, oc, MEM_SIZE);
return *this;
}
Matrix& operator=(const Matrix& o) {
if (o.ROWS!=ROWS&&o.COLUMNS!=COLUMNS) {
delete[] _c;
ROWS = o.ROWS;
COLUMNS = o.COLUMNS;
SIZE = o.SIZE;
MEM_SIZE = o.MEM_SIZE;
_c = new TYPE[SIZE];
}
memcpy(_c, o._c, MEM_SIZE);
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 res(COLUMNS, ROWS);
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(COLUMNS, ROWS);
for (TYPE *to((TYPE*)(res._c)+SIZE); to>(TYPE*)(_c); --to) *to = -*to;
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
protected:
void copy_args(TYPE*) {}
template<typename ...ARGS>
void copy_args(TYPE* to, TYPE t1, ARGS...t) {
*to = t1;
copy_args(++to, t...);
}
//..............................................................variables
protected:
TYPE* _c;
};
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> res(m1);
return res+=m2;
}
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';
}
}