more operator, more checks passed

master
Marc Wäckerlin 8 years ago
parent 9d6f92f41c
commit 8f37bef3e9
  1. 187
      src/matrix.hxx
  2. 84
      test/basic.cxx

@ -10,15 +10,15 @@
#include <cassert> #include <cassert>
#include <type_traits> #include <type_traits>
#define LOG std::cout<<__PRETTY_FUNCTION__<<std::endl template<typename TYPE, size_t TROWS=0, size_t TCOLUMNS=0> class Matrix {
template<typename T, size_t ROWS=0, size_t COLUMNS=0> class Matrix {
//........................................................const.variables //........................................................const.variables
protected: public:
static const size_t ROWS = TROWS;
static const size_t COLUMNS = TCOLUMNS;
static const size_t SIZE = ROWS*COLUMNS; static const size_t SIZE = ROWS*COLUMNS;
static const size_t MEM_SIZE = ROWS*COLUMNS*sizeof(T); static const size_t MEM_SIZE = ROWS*COLUMNS*sizeof(TYPE);
//...............................................................typedefs //...............................................................typedefs
public: public:
@ -35,27 +35,27 @@ template<typename T, size_t ROWS=0, size_t COLUMNS=0> class Matrix {
@endcode */ @endcode */
class RowVector { class RowVector {
public: public:
T& operator[](size_t column) { TYPE& operator[](size_t column) {
return _v[column]; return _v[column];
} }
protected: protected:
friend class Matrix; friend class Matrix;
RowVector() = delete; // forbidden RowVector() = delete; // forbidden
RowVector(T c[COLUMNS]): _v(c) {} RowVector(TYPE c[COLUMNS]): _v(c) {}
T *_v; TYPE *_v;
}; };
/// Same as RowVector, but in a constant environment. /// Same as RowVector, but in a constant environment.
class ConstRowVector { class ConstRowVector {
public: public:
const T& operator[](size_t column) const { const TYPE& operator[](size_t column) const {
return _v[column]; return _v[column];
} }
protected: protected:
friend class Matrix; friend class Matrix;
ConstRowVector() = delete; // forbidden ConstRowVector() = delete; // forbidden
ConstRowVector(const T c[COLUMNS]): _v(c) {} ConstRowVector(const TYPE c[COLUMNS]): _v(c) {}
const T *_v; const TYPE *_v;
}; };
///} ///}
@ -67,18 +67,15 @@ template<typename T, size_t ROWS=0, size_t COLUMNS=0> class Matrix {
///{ ///{
Matrix() { Matrix() {
LOG;
memset(_c, 0, MEM_SIZE); memset(_c, 0, MEM_SIZE);
} }
template<typename ...ARGS> template<typename ...ARGS>
Matrix(ARGS...t): _c{std::forward<T>(t)...} { Matrix(ARGS...t): _c{std::forward<TYPE>(t)...} {
LOG;
static_assert(sizeof...(t)==SIZE, "variadic matrix initialisation requires correct array size"); static_assert(sizeof...(t)==SIZE, "variadic matrix initialisation requires correct array size");
} }
Matrix(const Matrix& o) { Matrix(const Matrix& o) {
LOG;
memcpy(_c, o._c, MEM_SIZE); memcpy(_c, o._c, MEM_SIZE);
} }
@ -87,30 +84,76 @@ template<typename T, size_t ROWS=0, size_t COLUMNS=0> class Matrix {
/// @name operators /// @name operators
///{ ///{
Matrix& operator=(T oc[ROWS][COLUMNS]) { Matrix& operator=(TYPE oc[ROWS][COLUMNS]) {
LOG;
memcpy(_c, oc, MEM_SIZE); memcpy(_c, oc, MEM_SIZE);
return *this; return *this;
} }
Matrix& operator=(const Matrix& o) { Matrix& operator=(const Matrix& o) {
LOG;
memcpy(_c, o._c, MEM_SIZE); memcpy(_c, o._c, MEM_SIZE);
return *this; 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) { Matrix& operator+=(const Matrix& o) {
LOG; TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE);
T *to((T*)(_c)+MEM_SIZE), *from((T*)(o._c)+MEM_SIZE); while (to>(TYPE*)(_c)) *--to += *--from;
while (to>(T*)(_c)) *--to += *--from;
return *this; 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) { RowVector operator[](size_t row) {
assert(row<ROWS);
return RowVector(_c[row]); return RowVector(_c[row]);
} }
const ConstRowVector operator[](size_t row) const { const ConstRowVector operator[](size_t row) const {
assert(row<ROWS);
return ConstRowVector(_c[row]); return ConstRowVector(_c[row]);
} }
@ -119,11 +162,11 @@ template<typename T, size_t ROWS=0, size_t COLUMNS=0> class Matrix {
//..............................................................variables //..............................................................variables
protected: protected:
T _c[ROWS][COLUMNS]; TYPE _c[ROWS][COLUMNS];
}; };
template<typename T> class Matrix<T, 0, 0> { template<typename TYPE> class Matrix<TYPE, 0, 0> {
//..............................................................constants //..............................................................constants
public: public:
@ -148,31 +191,31 @@ template<typename T> class Matrix<T, 0, 0> {
@endcode */ @endcode */
class RowVector { class RowVector {
public: public:
T& operator[](size_t column) { TYPE& operator[](size_t column) {
assert(column<_m.COLUMNS); assert(column<_m.COLUMNS);
return _v[column]; return _v[column];
} }
protected: protected:
friend class Matrix; friend class Matrix;
RowVector() = delete; // forbidden RowVector() = delete; // forbidden
RowVector(const Matrix& m, T c[]): _m(m), _v(c) {} RowVector(const Matrix& m, TYPE c[]): _m(m), _v(c) {}
const Matrix& _m; const Matrix& _m;
T *_v; TYPE *_v;
}; };
/// Same as RowVector, but in a constant environment. /// Same as RowVector, but in a constant environment.
class ConstRowVector { class ConstRowVector {
public: public:
const T& operator[](size_t column) const { const TYPE& operator[](size_t column) const {
assert(column<_m.COLUMNS); assert(column<_m.COLUMNS);
return _v[column]; return _v[column];
} }
protected: protected:
friend class Matrix; friend class Matrix;
ConstRowVector() = delete; // forbidden ConstRowVector() = delete; // forbidden
ConstRowVector(const Matrix& m, const T c[]): _m(m), _v(c) {} ConstRowVector(const Matrix& m, const TYPE c[]): _m(m), _v(c) {}
const Matrix& _m; const Matrix& _m;
const T *_v; const TYPE *_v;
}; };
///} ///}
@ -187,22 +230,19 @@ template<typename T> class Matrix<T, 0, 0> {
ROWS(rows), ROWS(rows),
COLUMNS(columns), COLUMNS(columns),
SIZE(rows*columns), SIZE(rows*columns),
MEM_SIZE(rows*columns*sizeof(T)), MEM_SIZE(rows*columns*sizeof(TYPE)),
_c(new T[rows*columns]) { _c(new TYPE[rows*columns]) {
LOG;
memset(_c, 0, MEM_SIZE); 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) {
LOG;
assert(sizeof...(t)==SIZE); assert(sizeof...(t)==SIZE);
copy_args(_c, t...); copy_args(_c, t...);
} }
Matrix(const Matrix& o): Matrix(o.ROWS, o.COLUMNS) { Matrix(const Matrix& o): Matrix(o.ROWS, o.COLUMNS) {
LOG;
memcpy(_c, o._c, MEM_SIZE); memcpy(_c, o._c, MEM_SIZE);
} }
@ -220,36 +260,83 @@ template<typename T> class Matrix<T, 0, 0> {
/// @name operators /// @name operators
///{ ///{
Matrix& operator=(T oc[]) { Matrix& operator=(TYPE oc[]) {
LOG;
assert(sizeof(oc)==MEM_SIZE); assert(sizeof(oc)==MEM_SIZE);
memcpy(_c, oc, MEM_SIZE); memcpy(_c, oc, MEM_SIZE);
return *this; return *this;
} }
Matrix& operator=(const Matrix& o) { Matrix& operator=(const Matrix& o) {
LOG;
if (o.ROWS!=ROWS&&o.COLUMNS!=COLUMNS) { if (o.ROWS!=ROWS&&o.COLUMNS!=COLUMNS) {
delete[] _c; delete[] _c;
ROWS = o.ROWS; ROWS = o.ROWS;
COLUMNS = o.COLUMNS; COLUMNS = o.COLUMNS;
SIZE = o.SIZE; SIZE = o.SIZE;
MEM_SIZE = o.MEM_SIZE; MEM_SIZE = o.MEM_SIZE;
_c = new T[SIZE]; _c = new TYPE[SIZE];
} }
memcpy(_c, o._c, MEM_SIZE); memcpy(_c, o._c, MEM_SIZE);
return *this; 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) { Matrix& operator+=(const Matrix& o) {
LOG;
assert(o.ROWS==ROWS); assert(o.ROWS==ROWS);
assert(o.COLUMNS==COLUMNS); assert(o.COLUMNS==COLUMNS);
T *to((T*)(_c)+MEM_SIZE), *from((T*)(o._c)+MEM_SIZE); TYPE *to((TYPE*)(_c)+SIZE), *from((TYPE*)(o._c)+SIZE);
while (to>(T*)(_c)) *--to += *--from; 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; 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) { RowVector operator[](size_t row) {
assert(row<ROWS); assert(row<ROWS);
return RowVector(*this, _c+row*COLUMNS); return RowVector(*this, _c+row*COLUMNS);
@ -265,9 +352,9 @@ template<typename T> class Matrix<T, 0, 0> {
//................................................................methods //................................................................methods
protected: protected:
void copy_args(T*) {} void copy_args(TYPE*) {}
template<typename ...ARGS> template<typename ...ARGS>
void copy_args(T* to, T t1, ARGS...t) { void copy_args(TYPE* to, TYPE t1, ARGS...t) {
*to = t1; *to = t1;
copy_args(++to, t...); copy_args(++to, t...);
} }
@ -275,20 +362,18 @@ template<typename T> class Matrix<T, 0, 0> {
//..............................................................variables //..............................................................variables
protected: protected:
T* _c; TYPE* _c;
}; };
template<typename T, size_t ROWS, size_t COLUMNS> template<typename TYPE, size_t ROWS, size_t COLUMNS>
Matrix<T, ROWS, COLUMNS> operator+(const Matrix<T, ROWS, COLUMNS>& m1, const Matrix<T, ROWS, COLUMNS>& m2) { Matrix<TYPE, ROWS, COLUMNS> operator+(const Matrix<TYPE, ROWS, COLUMNS>& m1, const Matrix<TYPE, ROWS, COLUMNS>& m2) {
LOG; Matrix<TYPE, ROWS, COLUMNS> res(m1);
Matrix<T, ROWS, COLUMNS> res(m1);
return res+=m2; return res+=m2;
} }
template<typename T, size_t ROWS, size_t COLUMNS> template<typename TYPE, size_t ROWS, size_t COLUMNS>
std::ostream& operator<<(std::ostream& s, const Matrix<T, ROWS, COLUMNS>& m) { std::ostream& operator<<(std::ostream& s, const Matrix<TYPE, ROWS, COLUMNS>& m) {
LOG;
for (size_t w = 0; w < m.ROWS; ++w) { for (size_t w = 0; w < m.ROWS; ++w) {
for (size_t h = 0; h < m.COLUMNS;++h) { for (size_t h = 0; h < m.COLUMNS;++h) {
s<<m[w][h]<<' '; s<<m[w][h]<<' ';

@ -80,13 +80,42 @@ class TemplateMatrixTest: public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL((T)8, m2[1][3]); CPPUNIT_ASSERT_EQUAL((T)8, m2[1][3]);
} }
template<typename T> template<typename T>
void initFromDefault() { void initFromDefault() {
Matrix<T,2,2> m; Matrix<T,2,2> m;
CPPUNIT_ASSERT_EQUAL((T)0, m[0][0]); CPPUNIT_ASSERT_EQUAL((T)0, m[0][0]);
CPPUNIT_ASSERT_EQUAL((T)0, m[0][1]); CPPUNIT_ASSERT_EQUAL((T)0, m[0][1]);
CPPUNIT_ASSERT_EQUAL((T)0, m[1][0]); CPPUNIT_ASSERT_EQUAL((T)0, m[1][0]);
CPPUNIT_ASSERT_EQUAL((T)0, m[1][1]); CPPUNIT_ASSERT_EQUAL((T)0, m[1][1]);
} }
template<typename T>
void access() {
Matrix<T,2,4> m1(1, 2, 3, 4,
5, 6, 7, 8);
for (size_t row(0); row<2; ++row)
for (size_t column(0); column<4; ++column)
CPPUNIT_ASSERT_EQUAL(m1(row, column), m1[row][column]);
}
template<typename T>
void equality() {
Matrix<T,2,4> m1(1, 2, 3, 4,
5, 6, 7, 8);
Matrix<T,2,4> m2(1, 2, 3, 4,
5, 6, 7, 8);
Matrix<T,2,4> m3(1, 2, 3, 4,
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);
}
CPPUNIT_TEST_SUITE(TemplateMatrixTest); CPPUNIT_TEST_SUITE(TemplateMatrixTest);
CPPUNIT_TEST(initFromArray1<int>); CPPUNIT_TEST(initFromArray1<int>);
CPPUNIT_TEST(initFromArray1<long>); CPPUNIT_TEST(initFromArray1<long>);
@ -112,6 +141,18 @@ class TemplateMatrixTest: public CppUnit::TestFixture {
CPPUNIT_TEST(initFromOtherMatrix<unsigned long>); CPPUNIT_TEST(initFromOtherMatrix<unsigned long>);
CPPUNIT_TEST(initFromOtherMatrix<float>); CPPUNIT_TEST(initFromOtherMatrix<float>);
CPPUNIT_TEST(initFromOtherMatrix<double>); CPPUNIT_TEST(initFromOtherMatrix<double>);
CPPUNIT_TEST(access<int>);
CPPUNIT_TEST(access<long>);
CPPUNIT_TEST(access<unsigned>);
CPPUNIT_TEST(access<unsigned long>);
CPPUNIT_TEST(access<float>);
CPPUNIT_TEST(access<double>);
CPPUNIT_TEST(equality<int>);
CPPUNIT_TEST(equality<long>);
CPPUNIT_TEST(equality<unsigned>);
CPPUNIT_TEST(equality<unsigned long>);
CPPUNIT_TEST(equality<float>);
CPPUNIT_TEST(equality<double>);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
}; };
CPPUNIT_TEST_SUITE_REGISTRATION(TemplateMatrixTest); CPPUNIT_TEST_SUITE_REGISTRATION(TemplateMatrixTest);
@ -173,13 +214,40 @@ class VariableMatrixTest: public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL((T)8, m2[1][3]); CPPUNIT_ASSERT_EQUAL((T)8, m2[1][3]);
} }
template<typename T> template<typename T>
void initFromDefault() { void initFromDefault() {
Matrix<T> m(2, 4); Matrix<T> m(2, 4);
CPPUNIT_ASSERT_EQUAL((T)0, m[0][0]); CPPUNIT_ASSERT_EQUAL((T)0, m[0][0]);
CPPUNIT_ASSERT_EQUAL((T)0, m[0][1]); CPPUNIT_ASSERT_EQUAL((T)0, m[0][1]);
CPPUNIT_ASSERT_EQUAL((T)0, m[1][0]); CPPUNIT_ASSERT_EQUAL((T)0, m[1][0]);
CPPUNIT_ASSERT_EQUAL((T)0, m[1][1]); CPPUNIT_ASSERT_EQUAL((T)0, m[1][1]);
} }
template<typename T>
void access() {
Matrix<T> m1(2, 4,
1, 2, 3, 4,
5, 6, 7, 8);
for (size_t row(0); row<2; ++row)
for (size_t column(0); column<4; ++column)
CPPUNIT_ASSERT_EQUAL(m1(row, column), m1[row][column]);
}
template<typename T>
void equality() {
Matrix<T> m1(2, 4,
1, 2, 3, 4,
5, 6, 7, 8);
Matrix<T> m2(2, 4,
1, 2, 3, 4,
5, 6, 7, 8);
Matrix<T> m3(2, 4,
1, 2, 3, 4,
5, 6, 7, 9);
Matrix<T> m4(2, 4,
9, 2, 3, 4,
5, 6, 7, 8);
CPPUNIT_ASSERT(m1==m2);
CPPUNIT_ASSERT(m1!=m3);
CPPUNIT_ASSERT(m1!=m4);
}
CPPUNIT_TEST_SUITE(VariableMatrixTest); CPPUNIT_TEST_SUITE(VariableMatrixTest);
CPPUNIT_TEST(initFromArray1<int>); CPPUNIT_TEST(initFromArray1<int>);
CPPUNIT_TEST(initFromArray1<long>); CPPUNIT_TEST(initFromArray1<long>);
@ -199,6 +267,18 @@ class VariableMatrixTest: public CppUnit::TestFixture {
CPPUNIT_TEST(initFromOtherMatrix<unsigned long>); CPPUNIT_TEST(initFromOtherMatrix<unsigned long>);
CPPUNIT_TEST(initFromOtherMatrix<float>); CPPUNIT_TEST(initFromOtherMatrix<float>);
CPPUNIT_TEST(initFromOtherMatrix<double>); CPPUNIT_TEST(initFromOtherMatrix<double>);
CPPUNIT_TEST(access<int>);
CPPUNIT_TEST(access<long>);
CPPUNIT_TEST(access<unsigned>);
CPPUNIT_TEST(access<unsigned long>);
CPPUNIT_TEST(access<float>);
CPPUNIT_TEST(access<double>);
CPPUNIT_TEST(equality<int>);
CPPUNIT_TEST(equality<long>);
CPPUNIT_TEST(equality<unsigned>);
CPPUNIT_TEST(equality<unsigned long>);
CPPUNIT_TEST(equality<float>);
CPPUNIT_TEST(equality<double>);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
}; };
CPPUNIT_TEST_SUITE_REGISTRATION(VariableMatrixTest); CPPUNIT_TEST_SUITE_REGISTRATION(VariableMatrixTest);

Loading…
Cancel
Save