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 { ...@@ -58,7 +58,7 @@ namespace AMDiS {
refinementPath(0), refinementPath(0),
refinementPathLength(0) refinementPathLength(0)
{ {
projection.set(NULL); projection.set((Projection*)(NULL));
for (int i = 0; i < neighbourCoord.getSize(); i++) for (int i = 0; i < neighbourCoord.getSize(); i++)
neighbourCoord[i].init(mesh->getDim()); neighbourCoord[i].init(mesh->getDim());
......
...@@ -413,40 +413,33 @@ namespace AMDiS { ...@@ -413,40 +413,33 @@ namespace AMDiS {
WorldVector(InitType initType, const T& ini) WorldVector(InitType initType, const T& ini)
: super(Global::getGeo(WORLD), initType, 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 /// Copy constructor for other of same value_type
WorldVector(self const& other) WorldVector(self const& other)
: super(other) : super(other)
{} {}
/// Assignement operator /// Copy assignement operator
template <typename S> self& operator=(self other)
inline self& operator=(const Vector<S>& rhs)
{ {
this->setValues(rhs.getValArray()); swap(*this, other);
return *this; return *this;
} }
/// Assignement operator /// 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; return *this;
} }
/// Sets all entries to scal /// Sets all entries to scal
template <typename S> 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) operator=(S scal)
{ {
this->set(scal); this->set(scal);
...@@ -507,40 +500,35 @@ namespace AMDiS { ...@@ -507,40 +500,35 @@ namespace AMDiS {
this->set(ini); this->set(ini);
} }
// /// Copy constructor for other of different value_type /// Copy constructor
// template <typename S>
// WorldMatrix(Matrix<S> const& other)
// : super(Global::getGeo(WORLD), Global::getGeo(WORLD))
// {
// this->setValues(other.getValArray());
// }
//
// /// Copy constructor
WorldMatrix(self const& other) WorldMatrix(self const& other)
: super(other) : super(other)
{ } { }
/// Assignement operator /// Copy assignment operator
template <typename S> self& operator=(self other)
inline self& operator=(const Matrix<S>& rhs)
{ {
this->setValues(rhs.getValArray()); swap(*this, other);
return *this; return *this;
} }
/// Assignement operator /// Assignment operator
inline self& operator=(const self& rhs) 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; return *this;
} }
/// Assignement operator for scalars /// Assignment operator for scalars
template <typename S> template <typename S>
typename enable_if<boost::is_convertible<S, T>, WorldMatrix<T> >::type & 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; return *this;
} }
......
...@@ -41,13 +41,14 @@ namespace AMDiS { ...@@ -41,13 +41,14 @@ namespace AMDiS {
TEST_EXIT_DBG(m.getNumRows() == this->getSize())("invalide size\n"); TEST_EXIT_DBG(m.getNumRows() == this->getSize())("invalide size\n");
TEST_EXIT_DBG(v.getSize() == 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(); for (thisIt = this->begin(), mIt = m.begin();
thisIt != this->end(); thisIt != this->end();
thisIt++) { thisIt++) {
*thisIt = 0; *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; *thisIt += *vIt * *mIt;
} }
} }
...@@ -91,8 +92,8 @@ namespace AMDiS { ...@@ -91,8 +92,8 @@ namespace AMDiS {
T *thisIt = this->begin(); T *thisIt = this->begin();
for (T* v1It = v1.begin(); v1It != v1.end(); v1It++) for (T const* v1It = v1.begin(); v1It != v1.end(); v1It++)
for (T* v2It = v2.begin(); v2It != v2.end(); v2It++, thisIt++) for (T const* v2It = v2.begin(); v2It != v2.end(); v2It++, thisIt++)
*thisIt = *v1It * *v2It; *thisIt = *v1It * *v2It;
} }
......
...@@ -42,8 +42,8 @@ namespace AMDiS { ...@@ -42,8 +42,8 @@ namespace AMDiS {
elType(0), elType(0),
deserializedNeighbourIndices(NULL) deserializedNeighbourIndices(NULL)
{ {
neighbour.set(NULL); neighbour.set((MacroElement*)(NULL));
projection.set(NULL); projection.set((Projection*)(NULL));
} }
......
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
#ifndef AMDIS_MATRIXVECTOR_H #ifndef AMDIS_MATRIXVECTOR_H
#define AMDIS_MATRIXVECTOR_H #define AMDIS_MATRIXVECTOR_H
#include <vector> // #include <vector>
#include "Global.h" #include "Global.h"
#include "AMDiS_fwd.h" // #include "AMDiS_fwd.h"
#include "Serializable.h" #include "Serializable.h"
#include "traits/basic.hpp" // not dependenciess on other AMDiS types #include "traits/basic.hpp" // not dependenciess on other AMDiS types
...@@ -43,23 +43,22 @@ namespace AMDiS { ...@@ -43,23 +43,22 @@ namespace AMDiS {
typedef Vector self; typedef Vector self;
/// Constructor. /// Constructor.
Vector(int i = 0) Vector(int s = 0)
: size(0), : size(s),
valArray(NULL) valArray(size ? new T[size] : NULL)
{ { }
resize(i);
}
/// Copy constructor. /// Copy constructor.
Vector(self const& rhs) Vector(self const& other)
: Serializable(), : Serializable(),
size(rhs.getSize()), size(other.size),
valArray(new T[rhs.getSize()]) valArray(size ? new T[size] : NULL)
{ {
setValues(rhs.getValArray()); setValues(other.valArray);
} }
/// Copy constructor for other of different value_type /// Copy constructor for other of different value_type
// TODO: notwendig?
template <typename S> template <typename S>
Vector(Vector<S> const& rhs) Vector(Vector<S> const& rhs)
: Serializable(), : Serializable(),
...@@ -68,9 +67,18 @@ namespace AMDiS { ...@@ -68,9 +67,18 @@ namespace AMDiS {
{ {
setValues(rhs.getValArray()); setValues(rhs.getValArray());
} }
#if HAS_RVALUE_REFERENCES
/// move constructor
Vector(self&& other)
: Vector()
{
swap(*this, other);
}
#endif
/// Destructor. /// Destructor.
virtual ~Vector() ~Vector()
{ {
if (valArray != NULL) { if (valArray != NULL) {
delete [] valArray; delete [] valArray;
...@@ -96,74 +104,59 @@ namespace AMDiS { ...@@ -96,74 +104,59 @@ namespace AMDiS {
/// Assignement operator /// Assignement operator
template <typename S> 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()); resize(other.getSize());
this->setValues(rhs.getValArray()); setValues(other.getValArray());
return *this; return *this;
} }
inline self& operator=(self const& rhs) /// copy assignment operator
self& operator=(self other)
{ {
resize(rhs.getSize()); swap(*this, other);
this->setValues(rhs.getValArray());
return *this; return *this;
} }
/// Assignement operator for scalars /// Assignement operator for scalars
template <typename S> template <typename S>
typename enable_if<boost::is_convertible<S, T>, Vector<T> >::type & typename enable_if< boost::is_convertible<S, T>, Vector<T> >::type &
operator=(const S& scal) operator=(S value)
{ {
for (T *thisIt = this->begin(); thisIt != this->end(); ++thisIt) set(value);
*thisIt = scal;
return *this; return *this;
} }
/// Assignement operator /// Assignement operator
inline self& operator=(const T* vec) inline self& operator=(const T* vec)
{ {
this->setValues(vec); setValues(vec);
return *this; return *this;
} }
/// Sets all entries to scal. /// A swap function for Vector, used in the Copy-and-swap idiom
template <typename S> // need non-templated arguments in order to eliminate a friend declaration warning in gcc
inline typename disable_if<and_<boost::is_integral<S>, boost::is_pointer<T> >, Vector<T>& >::type friend void swap(Vector& first, Vector& second)
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
{ {
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> 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. /// Sets all entries.
template <typename S> template <typename S>
void setValues(const S* values) void setValues(const S* values)
{ {
typedef typename and_< boost::is_same<S,T>, traits::is_trivially_copyable<S> >::type use_memcpy; std::copy(values, values + size, valArray);
setValues_aux(values, use_memcpy());
}
/// Sets all entries.
inline void fill(T value)
{
std::fill(valArray, valArray + size, value);
} }
/// Comparison operator. /// Comparison operator.
...@@ -172,11 +165,12 @@ namespace AMDiS { ...@@ -172,11 +165,12 @@ namespace AMDiS {
if (size != rhs.size) if (size != rhs.size)
return false; return false;
T *rhsIt, *thisIt; T const* rhsIt;
T const* thisIt;
for (rhsIt = rhs.begin(), thisIt = this->begin(); for (rhsIt = rhs.begin(), thisIt = this->begin();
rhsIt != rhs.end(); rhsIt != rhs.end();
++rhsIt, ++thisIt) ++rhsIt, ++thisIt)
if(*thisIt != *rhsIt) if (*thisIt != *rhsIt)
return false; return false;
return true; return true;
...@@ -191,28 +185,24 @@ namespace AMDiS { ...@@ -191,28 +185,24 @@ namespace AMDiS {
/// Access to the i-th vector element. /// Access to the i-th vector element.
inline T& operator[](int i) 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]; return valArray[i];
} }
/// Access to the i-th vector element for const vectors. /// Access to the i-th vector element for const vectors.
inline const T& operator[] (int i) const 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]; return valArray[i];
} }
/// Returns pointer to the first vector element. /// Returns pointer to the first vector element.
inline T *begin() const inline T* begin() { return valArray; }
{ inline T const* begin() const { return valArray; }
return valArray;
}
/// Returns pointer after the last vector element. /// Returns pointer after the last vector element.
inline T *end() const inline T* end() { return valArray + size; }
{ inline T const* end() const { return valArray + size; }
return valArray + size;
}
/// Returns \ref size. /// Returns \ref size.
inline int getSize() const inline int getSize() const
...@@ -221,15 +211,8 @@ namespace AMDiS { ...@@ -221,15 +211,8 @@ namespace AMDiS {
} }
/// Returns \ref valArray as T-array /// Returns \ref valArray as T-array
inline T* getValArray() inline T* getValArray() { return valArray; }
{ inline T const* getValArray() const { return valArray; }
return valArray;
}
inline T const* getValArray() const
{
return valArray;
}
void print() const void print() const
{ {
...@@ -275,7 +258,7 @@ namespace AMDiS { ...@@ -275,7 +258,7 @@ namespace AMDiS {
/// Default constructor. /// Default constructor.
Matrix() Matrix()
: Vector<T>(0), rows(0), cols(0) : super(0), rows(0), cols(0)
{} {}
/// Constructor. /// Constructor.
...@@ -285,55 +268,74 @@ namespace AMDiS { ...@@ -285,55 +268,74 @@ namespace AMDiS {
cols(c) cols(c)
{} {}
/// copy constructor
Matrix(self const& other) Matrix(self const& other)
: super(other), : super(other),
rows(other.getNumRows()), rows(other.getNumRows()),
cols(other.getNumCols()) 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. /// Changes the size of the matrix to newRows x newCols.
inline void resize(int newRows, int newCols) inline void resize(int newRows, int newCols)
{ {
if ((newRows != rows) || (newCols != cols)) { if ((newRows != rows) || (newCols != cols)) {
Vector<T>::resize(newRows * newCols); super::resize(newRows * newCols);
rows = newRows; rows = newRows;
cols = newCols; cols = newCols;
} }
} }
/// Assignement operator self& operator=(self other)
template <typename S>
inline self& operator=(const Matrix<S>& rhs)
{ {
resize(rhs.getNumRows(), rhs.getNumCols()); swap(*this, other);
this->setValues(rhs.getValArray());
return *this; 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()); resize(other.getNumRows(), other.getNumCols());
this->setValues(rhs.getValArray()); this->setValues(other.getValArray());
return *this; return *this;
} }
/// Assignement operator for scalars. /// Assignement operator for scalars.
inline Matrix<T>& operator=(const T& scal) self& operator=(T value)
{ {
Vector<T>::operator=(scal); super::set(value);
return *this; 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