Commit c5398967 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Matrix, Vector and FixVec now follow the copy-and-swap idiom

parent 5fb3baff
......@@ -58,7 +58,7 @@ namespace AMDiS {
refinementPath(0),
refinementPathLength(0)
{
projection.set(NULL);
projection.set((Projection*)(NULL));
for (int i = 0; i < neighbourCoord.getSize(); i++)
neighbourCoord[i].init(mesh->getDim());
......
......@@ -413,40 +413,33 @@ namespace AMDiS {
WorldVector(InitType initType, const T& ini)
: super(Global::getGeo(WORLD), initType, ini)
{}
// /// Copy constructor for other of different value_type
// template <typename S>
// WorldVector(Vector<S> const& other)
// : super(Global::getGeo(WORLD), NO_INIT)
// {
// operator=(other);
// }
//
/// Copy constructor for other of same value_type
WorldVector(self const& other)
: super(other)
{}
/// Assignement operator
template <typename S>
inline self& operator=(const Vector<S>& rhs)
/// Copy assignement operator
self& operator=(self other)
{
this->setValues(rhs.getValArray());
swap(*this, other);
return *this;
}
/// Assignement operator
inline self& operator=(const self& rhs)
template <typename S>
self& operator=(const Vector<S>& other)
{
this->setValues(rhs.getValArray());
TEST_EXIT_DBG( other.getSize() == Global::getGeo(WORLD) )
("Wrong dimensions in assignment.\n");
this->setValues(other.getValArray());
return *this;
}
/// Sets all entries to scal
template <typename S>
typename enable_if<boost::is_convertible<S, T>, WorldVector<T> >::type &
typename enable_if<boost::is_convertible<S, T>, self>::type &
operator=(S scal)
{
this->set(scal);
......@@ -507,40 +500,35 @@ namespace AMDiS {
this->set(ini);
}
// /// Copy constructor for other of different value_type
// template <typename S>
// WorldMatrix(Matrix<S> const& other)
// : super(Global::getGeo(WORLD), Global::getGeo(WORLD))
// {
// this->setValues(other.getValArray());
// }
//
// /// Copy constructor
/// Copy constructor
WorldMatrix(self const& other)
: super(other)
{ }
/// Assignement operator
template <typename S>
inline self& operator=(const Matrix<S>& rhs)
/// Copy assignment operator
self& operator=(self other)
{
this->setValues(rhs.getValArray());
swap(*this, other);
return *this;
}
/// Assignement operator
inline self& operator=(const self& rhs)
/// Assignment operator
template <typename S>
self& operator=(const Matrix<S>& other)
{
this->setValues(rhs.getValArray());
TEST_EXIT_DBG( other.getNumOfRows() == Global::getGeo(WORLD) &&
other.getNumOfCols() == Global::getGeo(WORLD) )
("Wrong dimensions in assignment.\n");
this->setValues(other.getValArray());
return *this;
}
/// Assignement operator for scalars
/// Assignment operator for scalars
template <typename S>
typename enable_if<boost::is_convertible<S, T>, WorldMatrix<T> >::type &
operator=(S rhs)
operator=(S value)
{
this->set(rhs);
this->set(value);
return *this;
}
......
......@@ -41,13 +41,14 @@ namespace AMDiS {
TEST_EXIT_DBG(m.getNumRows() == this->getSize())("invalide size\n");
TEST_EXIT_DBG(v.getSize() == this->getSize())("invalide size\n");
T *mIt, *thisIt;
T const* mIt;
T* thisIt;
for (thisIt = this->begin(), mIt = m.begin();
thisIt != this->end();
thisIt++) {
*thisIt = 0;
for (T* vIt = v.begin(); vIt != v.end(); vIt++, mIt++)
for (T const* vIt = v.begin(); vIt != v.end(); vIt++, mIt++)
*thisIt += *vIt * *mIt;
}
}
......@@ -91,8 +92,8 @@ namespace AMDiS {
T *thisIt = this->begin();
for (T* v1It = v1.begin(); v1It != v1.end(); v1It++)
for (T* v2It = v2.begin(); v2It != v2.end(); v2It++, thisIt++)
for (T const* v1It = v1.begin(); v1It != v1.end(); v1It++)
for (T const* v2It = v2.begin(); v2It != v2.end(); v2It++, thisIt++)
*thisIt = *v1It * *v2It;
}
......
......@@ -42,8 +42,8 @@ namespace AMDiS {
elType(0),
deserializedNeighbourIndices(NULL)
{
neighbour.set(NULL);
projection.set(NULL);
neighbour.set((MacroElement*)(NULL));
projection.set((Projection*)(NULL));
}
......
......@@ -25,9 +25,9 @@
#ifndef AMDIS_MATRIXVECTOR_H
#define AMDIS_MATRIXVECTOR_H
#include <vector>
// #include <vector>
#include "Global.h"
#include "AMDiS_fwd.h"
// #include "AMDiS_fwd.h"
#include "Serializable.h"
#include "traits/basic.hpp" // not dependenciess on other AMDiS types
......@@ -43,23 +43,22 @@ namespace AMDiS {
typedef Vector self;
/// Constructor.
Vector(int i = 0)
: size(0),
valArray(NULL)
{
resize(i);
}
Vector(int s = 0)
: size(s),
valArray(size ? new T[size] : NULL)
{ }
/// Copy constructor.
Vector(self const& rhs)
Vector(self const& other)
: Serializable(),
size(rhs.getSize()),
valArray(new T[rhs.getSize()])
size(other.size),
valArray(size ? new T[size] : NULL)
{
setValues(rhs.getValArray());
setValues(other.valArray);
}
/// Copy constructor for other of different value_type
// TODO: notwendig?
template <typename S>
Vector(Vector<S> const& rhs)
: Serializable(),
......@@ -68,9 +67,18 @@ namespace AMDiS {
{
setValues(rhs.getValArray());
}
#if HAS_RVALUE_REFERENCES
/// move constructor
Vector(self&& other)
: Vector()
{
swap(*this, other);
}
#endif
/// Destructor.
virtual ~Vector()
~Vector()
{
if (valArray != NULL) {
delete [] valArray;
......@@ -96,74 +104,59 @@ namespace AMDiS {
/// Assignement operator
template <typename S>
inline self& operator=(Vector<S> const& rhs)
typename disable_if< boost::is_same<S, T>, self >::type &
operator=(Vector<S> const& other)
{
resize(rhs.getSize());
this->setValues(rhs.getValArray());
resize(other.getSize());
setValues(other.getValArray());
return *this;
}
inline self& operator=(self const& rhs)
/// copy assignment operator
self& operator=(self other)
{
resize(rhs.getSize());
this->setValues(rhs.getValArray());
swap(*this, other);
return *this;
}
/// Assignement operator for scalars
template <typename S>
typename enable_if<boost::is_convertible<S, T>, Vector<T> >::type &
operator=(const S& scal)
typename enable_if< boost::is_convertible<S, T>, Vector<T> >::type &
operator=(S value)
{
for (T *thisIt = this->begin(); thisIt != this->end(); ++thisIt)
*thisIt = scal;
set(value);
return *this;
}
/// Assignement operator
inline self& operator=(const T* vec)
{
this->setValues(vec);
setValues(vec);
return *this;
}
/// Sets all entries to scal.
template <typename S>
inline typename disable_if<and_<boost::is_integral<S>, boost::is_pointer<T> >, Vector<T>& >::type
set(S const& scal)
{
return *this = scal;
}
inline Vector<T>& set(T const& scal)
{
return *this = scal;
}
void setValues_aux(const T* values, true_) // trivially copyable
/// A swap function for Vector, used in the Copy-and-swap idiom
// need non-templated arguments in order to eliminate a friend declaration warning in gcc
friend void swap(Vector& first, Vector& second)
{
std::memcpy(valArray, values, sizeof(T)*size);
using std::swap; // enable ADL
swap(first.size, second.size);
swap(first.valArray, second.valArray);
}
/// Sets all entries to scal.
template <typename S>
void setValues_aux(const S* values, false_) // NOT trivially copyable
typename enable_if< boost::is_convertible<S, T> >::type
set(S value)
{
std::copy(values, values + size, valArray);
std::fill(begin(), end(), value);
}
/// Sets all entries.
template <typename S>
void setValues(const S* values)
{
typedef typename and_< boost::is_same<S,T>, traits::is_trivially_copyable<S> >::type use_memcpy;
setValues_aux(values, use_memcpy());
}
/// Sets all entries.
inline void fill(T value)
{
std::fill(valArray, valArray + size, value);
std::copy(values, values + size, valArray);
}
/// Comparison operator.
......@@ -172,11 +165,12 @@ namespace AMDiS {
if (size != rhs.size)
return false;
T *rhsIt, *thisIt;
T const* rhsIt;
T const* thisIt;
for (rhsIt = rhs.begin(), thisIt = this->begin();
rhsIt != rhs.end();
++rhsIt, ++thisIt)
if(*thisIt != *rhsIt)
if (*thisIt != *rhsIt)
return false;
return true;
......@@ -191,28 +185,24 @@ namespace AMDiS {
/// Access to the i-th vector element.
inline T& operator[](int i)
{
TEST_EXIT_DBG(i < size && i >= 0)("Invalid index %d!\n", i);
// TEST_EXIT_DBG(i < size && i >= 0)("Invalid index %d!\n", i);
return valArray[i];
}
/// Access to the i-th vector element for const vectors.
inline const T& operator[] (int i) const
{
TEST_EXIT_DBG(i < size && i >= 0)("Invalid index %d!\n", i);
// TEST_EXIT_DBG(i < size && i >= 0)("Invalid index %d!\n", i);
return valArray[i];
}
/// Returns pointer to the first vector element.
inline T *begin() const
{
return valArray;
}
inline T* begin() { return valArray; }
inline T const* begin() const { return valArray; }
/// Returns pointer after the last vector element.
inline T *end() const
{
return valArray + size;
}
inline T* end() { return valArray + size; }
inline T const* end() const { return valArray + size; }
/// Returns \ref size.
inline int getSize() const
......@@ -221,15 +211,8 @@ namespace AMDiS {
}
/// Returns \ref valArray as T-array
inline T* getValArray()
{
return valArray;
}
inline T const* getValArray() const
{
return valArray;
}
inline T* getValArray() { return valArray; }
inline T const* getValArray() const { return valArray; }
void print() const
{
......@@ -275,7 +258,7 @@ namespace AMDiS {
/// Default constructor.
Matrix()
: Vector<T>(0), rows(0), cols(0)
: super(0), rows(0), cols(0)
{}
/// Constructor.
......@@ -285,55 +268,74 @@ namespace AMDiS {
cols(c)
{}
/// copy constructor
Matrix(self const& other)
: super(other),
rows(other.getNumRows()),
cols(other.getNumCols())
{ }
#if HAS_RVALUE_REFERENCES
/// move constructor
Matrix(self&& other)
: Matrix()
{
swap(*this, other);
}
#endif
/// Changes the size of the matrix to newRows x newCols.
inline void resize(int newRows, int newCols)
{
if ((newRows != rows) || (newCols != cols)) {
Vector<T>::resize(newRows * newCols);
super::resize(newRows * newCols);
rows = newRows;
cols = newCols;
}
}
/// Assignement operator
template <typename S>
inline self& operator=(const Matrix<S>& rhs)
self& operator=(self other)
{
resize(rhs.getNumRows(), rhs.getNumCols());
this->setValues(rhs.getValArray());
swap(*this, other);
return *this;
}
inline self& operator=(self const& rhs)
/// Assignement operator
template <typename S>
inline self& operator=(const Matrix<S>& other)
{
resize(rhs.getNumRows(), rhs.getNumCols());
this->setValues(rhs.getValArray());
resize(other.getNumRows(), other.getNumCols());
this->setValues(other.getValArray());
return *this;
}
/// Assignement operator for scalars.
inline Matrix<T>& operator=(const T& scal)
self& operator=(T value)
{
Vector<T>::operator=(scal);
super::set(value);
return *this;
}
/// A swap function for Matrix, used in the Copy-and-swap idiom
// need non-templated arguments in order to eliminate a friend declaration warning in gcc
friend void swap(Matrix& first, Matrix& second)
{
using std::swap; // enable ADL
swap(first.rows, second.rows);
swap(first.cols, second.cols);
swap(static_cast<super&>(first), static_cast<super&>(second));
}
///
inline bool operator==(const Matrix<T>& rhs) const
/// Comparison operator.
inline bool operator==(const self& rhs) const
{
if (rows != rhs.getNumRows()) return false;
if (cols != rhs.getNumCols()) return false;
return Vector<T>::operator == (rhs);
return super::operator==(rhs);
}
/// Comparison operator.
inline bool operator!=(const Matrix<T>& rhs) const
inline bool operator!=(const self& rhs) const
{
return !(*this == rhs);
}
......@@ -374,18 +376,6 @@ namespace AMDiS {
return cols;
}
/// Returns \ref rows.
// inline int getSize() const
// {
// return rows*cols;
// }
/// Returns pointer after the last vector element.
// inline T *end() const
// {
// return this->valArray + (cols * rows);
// }
void print() const
{
std::cout << this->rows << " x " << this->cols << " matrix: " << std::endl;
......
......@@ -39,7 +39,9 @@ namespace AMDiS {
TEST_EXIT_DBG(m.getNumCols() == v.getSize())("m and v not compatible\n");
TEST_EXIT_DBG(v.getSize() == result.getSize())("wrong result size\n");
T *resultIt, *mIt, *vIt;
T *resultIt;
T const* mIt;
T const* vIt;
for (resultIt = result.begin(), mIt = m.begin();
resultIt != result.end();
......@@ -58,7 +60,9 @@ namespace AMDiS {
{
TEST_EXIT_DBG(v1.getSize() == v2.getSize())("invalid size in test v1 == v2\n");
TEST_EXIT_DBG(v2.getSize() == result.getSize())("invalid size in test v2 == result\n");
T *v1It, *v2It, *resultIt;
T const* v1It;
T const* v2It;
T* resultIt;
for (v1It = v1.begin(), v2It = v2.begin(), resultIt = result.begin();
v1It != v1.end();
++v1It, ++v2It, ++resultIt)
......@@ -75,7 +79,8 @@ namespace AMDiS {
{
TEST_EXIT_DBG(v.getSize() == result.getSize())("invalid size\n");
T *vIt, *resultIt;
T const* vIt;
T* resultIt;
for (vIt = v.begin(), resultIt = result.begin();
vIt != v.end();
++vIt, ++resultIt)
......@@ -89,7 +94,8 @@ namespace AMDiS {
inline const Vector<T>& add(const Vector<T>& v, const T& scal, Vector<T>& result)
{
TEST_EXIT_DBG(v.getSize() == result.getSize())("invalid size\n");
T *vIt, *resultIt;
T const* vIt;
T* resultIt;
for (vIt = v.begin(), resultIt = result.begin();
vIt != v.end();
++vIt, ++resultIt)
......@@ -105,7 +111,8 @@ namespace AMDiS {
Vector<T> &y)
{
TEST_EXIT_DBG(x.getSize() == y.getSize())("invalid size\n");
T *xIt, *yIt;
T const* xIt;
T* yIt;
for (xIt = x.begin(), yIt = y.begin();
xIt != x.end();
++xIt, ++yIt)
......@@ -140,8 +147,8 @@ namespace AMDiS {
typename traits::mult_type<T,S>::type result;
nullify(result);
T *v1It;
S *v2It;
T const* v1It;
S const* v2It;
for (v1It = v1.begin(), v2It = v2.begin();
v1It != v1.end();
++v1It, ++v2It)
......@@ -220,7 +227,7 @@ namespace AMDiS {
Vector<T>& operator+=(Vector<T>& x, const Vector<S>& y)
{
T *xIt;
S *yIt;
S const* yIt;
for (xIt = x.begin(), yIt = y.begin(); xIt != x.end(); ++xIt, ++yIt)
*xIt += *yIt;
return x;
......@@ -238,8 +245,8 @@ namespace AMDiS {
template <typename T, typename S>
Vector<T>& operator-=(Vector<T>& x, const Vector<S>& y)
{
T *xIt;
S *yIt;
T* xIt;
S const* yIt;
for (xIt = x.begin(), yIt = y.begin(); xIt != x.end(); ++xIt, ++yIt)
*xIt -= *yIt;
return x;
......@@ -261,7 +268,7 @@ namespace AMDiS {
inline T norm(const Vector<T> *v)
{
T result; nullify(result);
for (T* vIt = v->begin(); vIt != v->end(); ++vIt)
for (T const* vIt = v->begin(); vIt != v->end(); ++vIt)
result += *vIt * *vIt;
return std::sqrt(result);
}
......@@ -300,8 +307,8 @@ namespace AMDiS {
typename traits::mult_type<T,S>::type result;
nullify(result);
T *v1It;
S *v2It;
T const* v1It;
S const* v2It;
for (v1It = v1.begin(), v2It = v2.begin();
v1It != v1.end();
++v1It, ++v2It)
......@@ -457,7 +464,7 @@ namespace AMDiS {
WorldMatrix<T>& operator+=(WorldMatrix<T>& m1, const WorldMatrix<S>& m2)
{
T* m1It;
S* m2It;
S const* m2It;