remove redundancy, collect common functionality in base class
This commit is contained in:
@@ -273,7 +273,7 @@ EOF
|
||||
AC_DEFUN([AX_USE_CXX], [
|
||||
m4_include(ax_cxx_compile_stdcxx_11.m4)
|
||||
AC_LANG(C++)
|
||||
AX_CXX_COMPILE_STDCXX_14(noext, optional)
|
||||
AX_CXX_COMPILE_STDCXX_11(noext, optional)
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CPP
|
||||
|
||||
|
@@ -32,7 +32,7 @@ AX_BUILD_EXAMPLES
|
||||
#AX_CHECK_QT([QT], [QtCore QtGui QtNetwork], [QtWidgets])
|
||||
#AX_REQUIRE_QT([QT], [QtCore QtGui QtNetwork], [QtWidgets])
|
||||
#AX_QT_NO_KEYWORDS
|
||||
AX_REQUIRE_STDCXX_14
|
||||
AX_REQUIRE_STDCXX_11
|
||||
|
||||
# create output
|
||||
AC_OUTPUT
|
||||
|
415
src/matrix.hxx
415
src/matrix.hxx
@@ -10,164 +10,8 @@
|
||||
#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;
|
||||
};
|
||||
template<typename TYPE, typename ARRAY=TYPE*> class MatrixBase {
|
||||
|
||||
///}
|
||||
|
||||
//................................................................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:
|
||||
|
||||
@@ -196,10 +40,10 @@ template<typename TYPE> class Matrix<TYPE, 0, 0> {
|
||||
return _v[column];
|
||||
}
|
||||
protected:
|
||||
friend class Matrix;
|
||||
friend class MatrixBase;
|
||||
RowVector() = delete; // forbidden
|
||||
RowVector(const Matrix& m, TYPE c[]): _m(m), _v(c) {}
|
||||
const Matrix& _m;
|
||||
RowVector(const MatrixBase& m, TYPE c[]): _m(m), _v(c) {}
|
||||
const MatrixBase& _m;
|
||||
TYPE *_v;
|
||||
};
|
||||
|
||||
@@ -211,10 +55,10 @@ template<typename TYPE> class Matrix<TYPE, 0, 0> {
|
||||
return _v[column];
|
||||
}
|
||||
protected:
|
||||
friend class Matrix;
|
||||
friend class MatrixBase;
|
||||
ConstRowVector() = delete; // forbidden
|
||||
ConstRowVector(const Matrix& m, const TYPE c[]): _m(m), _v(c) {}
|
||||
const Matrix& _m;
|
||||
ConstRowVector(const MatrixBase& m, const TYPE c[]): _m(m), _v(c) {}
|
||||
const MatrixBase& _m;
|
||||
const TYPE *_v;
|
||||
};
|
||||
|
||||
@@ -226,95 +70,55 @@ template<typename TYPE> class Matrix<TYPE, 0, 0> {
|
||||
/// @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);
|
||||
MatrixBase(size_t rows, size_t columns):
|
||||
ROWS(rows), COLUMNS(columns),
|
||||
SIZE(ROWS*COLUMNS), MEM_SIZE(SIZE*sizeof(TYPE)) {
|
||||
}
|
||||
|
||||
|
||||
template<typename ...ARGS>
|
||||
Matrix(size_t rows, size_t columns, ARGS...t):
|
||||
Matrix(rows, columns) {
|
||||
assert(sizeof...(t)==SIZE);
|
||||
copy_args(_c, t...);
|
||||
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)...} {
|
||||
}
|
||||
|
||||
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[]) {
|
||||
MatrixBase& 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];
|
||||
}
|
||||
MatrixBase& operator=(const MatrixBase& o) {
|
||||
assert_check(o);
|
||||
memcpy(_c, o._c, MEM_SIZE);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Matrix& o) const {
|
||||
if (o.ROWS!=ROWS||o.COLUMNS!=COLUMNS) return false;
|
||||
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 Matrix& o) const {
|
||||
bool operator!=(const MatrixBase& 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);
|
||||
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;
|
||||
}
|
||||
|
||||
Matrix& operator-=(const Matrix& o) {
|
||||
assert(o.ROWS==ROWS);
|
||||
assert(o.COLUMNS==COLUMNS);
|
||||
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;
|
||||
@@ -328,23 +132,23 @@ template<typename TYPE> class Matrix<TYPE, 0, 0> {
|
||||
TYPE& operator()(size_t row, size_t column) {
|
||||
assert(row<ROWS);
|
||||
assert(column<COLUMNS);
|
||||
return *(_c+row*COLUMNS+column);
|
||||
return *((TYPE*)_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);
|
||||
return *((TYPE*)_c+row*COLUMNS+column);
|
||||
}
|
||||
|
||||
RowVector operator[](size_t row) {
|
||||
assert(row<ROWS);
|
||||
return RowVector(*this, _c+row*COLUMNS);
|
||||
return RowVector(*this, (TYPE*)_c+row*COLUMNS);
|
||||
}
|
||||
|
||||
const ConstRowVector operator[](size_t row) const {
|
||||
assert(row<ROWS);
|
||||
return ConstRowVector(*this, _c+row*COLUMNS);
|
||||
return ConstRowVector(*this, (TYPE*)_c+row*COLUMNS);
|
||||
}
|
||||
|
||||
///}
|
||||
@@ -352,6 +156,160 @@ template<typename TYPE> class Matrix<TYPE, 0, 0> {
|
||||
//................................................................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<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) {
|
||||
@@ -359,13 +317,10 @@ template<typename TYPE> class Matrix<TYPE, 0, 0> {
|
||||
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);
|
||||
|
@@ -105,13 +105,6 @@ class TemplateMatrixTest: public CppUnit::TestFixture {
|
||||
5, 6, 7, 9);
|
||||
Matrix<T,2,4> m4(9, 2, 3, 4,
|
||||
5, 6, 7, 8);
|
||||
std::cout<<std::endl
|
||||
<<"m1 = "<<std::endl
|
||||
<<m1<<std::endl
|
||||
<<"m2 = "<<std::endl
|
||||
<<m2<<std::endl
|
||||
<<"m3 = "<<std::endl
|
||||
<<m3<<std::endl;
|
||||
CPPUNIT_ASSERT(m1==m2);
|
||||
CPPUNIT_ASSERT(m1!=m3);
|
||||
CPPUNIT_ASSERT(m1!=m4);
|
||||
|
Reference in New Issue
Block a user