remove redundancy, collect common functionality in base class

master
Marc Wäckerlin 8 years ago
parent 8f37bef3e9
commit 714df5dbc0
  1. 2
      COPYING
  2. 2
      INSTALL
  3. 2
      ax_init_standard_project.m4
  4. 2
      configure.ac
  5. 305
      src/matrix.hxx
  6. 7
      test/basic.cxx

@ -1 +1 @@
/usr/share/automake-1.15/COPYING /usr/share/automake-1.14/COPYING

@ -1 +1 @@
/usr/share/automake-1.15/INSTALL /usr/share/automake-1.14/INSTALL

@ -273,7 +273,7 @@ EOF
AC_DEFUN([AX_USE_CXX], [ AC_DEFUN([AX_USE_CXX], [
m4_include(ax_cxx_compile_stdcxx_11.m4) m4_include(ax_cxx_compile_stdcxx_11.m4)
AC_LANG(C++) AC_LANG(C++)
AX_CXX_COMPILE_STDCXX_14(noext, optional) AX_CXX_COMPILE_STDCXX_11(noext, optional)
AC_PROG_CXX AC_PROG_CXX
AC_PROG_CPP AC_PROG_CPP

@ -32,7 +32,7 @@ AX_BUILD_EXAMPLES
#AX_CHECK_QT([QT], [QtCore QtGui QtNetwork], [QtWidgets]) #AX_CHECK_QT([QT], [QtCore QtGui QtNetwork], [QtWidgets])
#AX_REQUIRE_QT([QT], [QtCore QtGui QtNetwork], [QtWidgets]) #AX_REQUIRE_QT([QT], [QtCore QtGui QtNetwork], [QtWidgets])
#AX_QT_NO_KEYWORDS #AX_QT_NO_KEYWORDS
AX_REQUIRE_STDCXX_14 AX_REQUIRE_STDCXX_11
# create output # create output
AC_OUTPUT AC_OUTPUT

@ -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;
@ -138,88 +132,106 @@ template<typename TYPE, size_t TROWS=0, size_t TCOLUMNS=0> class Matrix {
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
private:
typedef MatrixBase<TYPE, TYPE[TROWS][TCOLUMNS]> Parent;
//................................................................methods
public: public:
/// @name Auxiliary Classes /// @name construction
///{ ///{
/// Return One Row as Vector, internally used for element access Matrix(): Parent(TROWS, TCOLUMNS) {}
/** Only used to access values:
@code template<typename ...ARGS>
Matrix<int,4,4> m; Matrix(ARGS...t): Parent(TROWS, TCOLUMNS, t...) {
m[2][2] = 1; static_assert(sizeof...(t)==TROWS*TCOLUMNS,
@endcode */ "wrong array size");
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. Matrix(const Matrix& o): Matrix() {
class ConstRowVector { memcpy(Parent::_c, o._c, Parent::MEM_SIZE);
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;
};
///} ///}
/// @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 //................................................................methods
public: public:
@ -227,23 +239,20 @@ template<typename TYPE> class Matrix<TYPE, 0, 0> {
///{ ///{
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,8 +260,8 @@ template<typename TYPE> class Matrix<TYPE, 0, 0> {
/// @name destruction /// @name destruction
///{ ///{
~Matrix() { virtual ~Matrix() {
delete[] _c; delete[] Parent::_c;
} }
///} ///}
@ -260,98 +269,47 @@ template<typename TYPE> class Matrix<TYPE, 0, 0> {
/// @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 //................................................................methods
///{ protected:
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) { virtual void assert_check(const Matrix& o) const {
assert(row<ROWS); assert(o.ROWS==Parent::ROWS);
return RowVector(*this, _c+row*COLUMNS); assert(o.COLUMNS==Parent::COLUMNS);
} }
const ConstRowVector operator[](size_t row) const { virtual bool check(const Matrix& o) const {
assert(row<ROWS); return o.ROWS==Parent::ROWS && o.COLUMNS==Parent::COLUMNS;
return ConstRowVector(*this, _c+row*COLUMNS);
} }
///}
//................................................................methods
protected:
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);

@ -105,13 +105,6 @@ class TemplateMatrixTest: public CppUnit::TestFixture {
5, 6, 7, 9); 5, 6, 7, 9);
Matrix<T,2,4> m4(9, 2, 3, 4, Matrix<T,2,4> m4(9, 2, 3, 4,
5, 6, 7, 8); 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==m2);
CPPUNIT_ASSERT(m1!=m3); CPPUNIT_ASSERT(m1!=m3);
CPPUNIT_ASSERT(m1!=m4); CPPUNIT_ASSERT(m1!=m4);

Loading…
Cancel
Save