Page MenuHomec4science

field_iterator.hh
No OneTemporary

File Metadata

Created
Thu, Sep 26, 17:15

field_iterator.hh

/**
* file field_iterator.hh
*
* @author Till Junge <till.junge@epfl.ch>
*
* @date 12 Sep 2017
*
* @brief Defined a strongly defines proxy that iterates efficiently over a field
*
* @section LICENCE
*
* Copyright (C) 2017 Till Junge
*
* µSpectre is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3, or (at
* your option) any later version.
*
* µSpectre is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Emacs; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef FIELD_ITERATOR_H
#define FIELD_ITERATOR_H
#include <iterator>
#include "system/field.hh"
#include "system/field_collection.hh"
#include "common/common.hh"
#include "common/eigen_tools.hh"
#include <array>
#include <unsupported/Eigen/CXX11/Tensor>
namespace muSpectre {
namespace internal {
template <class FieldCollection, typename T, size_t NbComponents,
class value_type>
class FieldMap
{
public:
using TypedField = TypedFieldBase<FieldCollection, NbComponents, T>;
//! Default constructor
FieldMap() = delete;
FieldMap(FieldBase<FieldCollection> & field);
//! Copy constructor
FieldMap(const FieldMap &other) = delete;
//! Move constructor
FieldMap(FieldMap &&other) noexcept = delete;
//! Destructor
virtual ~FieldMap() noexcept = default;
//! Copy assignment operator
FieldMap& operator=(const FieldMap &other) = delete;
//! Move assignment operator
FieldMap& operator=(FieldMap &&other) noexcept = delete;
//! member access needs to be implemented by inheriting classes
//inline value_type operator[](Uint index);
//inline value_type operator[](Ccoord ccord);
class iterator
{
public:
using value_type = FieldMap::value_type;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::random_access_iterator_tag;
//! Default constructor
iterator() = delete;
//! constructor
inline iterator(Field & field, bool begin=true);
//! constructor for random access
inline iterator(Field & field, Uint index);
//! Copy constructor
iterator(const iterator &other) = default;
//! Move constructor
iterator(iterator &&other) noexcept = default;
//! Destructor
virtual ~iterator() noexcept = default;
//! Copy assignment operator
iterator& operator=(const iterator &other) = default;
//! Move assignment operator
iterator& operator=(iterator &&other) noexcept = default;
//! pre-increment
inline iterator & operator++();
//! post-increment
inline iterator operator++(int);
//! dereference
inline value_type & operator*() const;
//! pre-decrement
inline iterator & operator--();
//! post-decrement
inline iterator operator--(int);
//! access subscripting
inline value_type & operator[](difference_type diff);
//! equality
inline bool operator==(const iterator & other) const;
//! inequality
inline bool operator!=(const iterator & other) const;
//! div. comparisons
inline bool operator<(const iterator & other) const;
inline bool operator<=(const iterator & other) const;
inline bool operator>(const iterator & other) const;
inline bool operator>=(const iterator & other) const;
//! additions, subtractions and corresponding assignments
inline iterator operator+(difference_type diff) const;
inline iterator operator-(difference_type diff) const;
inline iterator& operator+=(difference_type diff);
inline iterator& operator-=(difference_type diff);
//! get pixel coordinates
inline Ccoord get_ccoord() const;
protected:
const FieldCollection & collection;
TypedField & field;
Uint index;
private:
};
protected:
const FieldCollection & collection;
TypedField & field;
private:
};
} // internal
/* ---------------------------------------------------------------------- */
template <class FieldCollection, typename T, Dim_t order, Dim_t dim>
class TensorFieldMap: FieldMap<FieldCollection, T,
SizesByOrder<order, dim>::Sizes::total_size,
Eigen::TensorMap<
Eigen::TensorFixedSize<
T, SizesByOrder<order, dim>::Sizes>>>
{
public:
using Ccoord = Ccoord_t<FieldCollection::get_spatial_dim()>;
using Sizes = SizesByOrder<order, dim>::Sizes;
using T_t = Eigen::TensorFixedSize<T, Sizes>;
using NbComponents = Sizes::total_size;
using value_type = Eigen::TensorMap<T_t>;
using parent = FieldMap<FieldCollection, T, NbComponents, value_type>;
//! Default constructor
TensorFieldMap() = delete;
TensorFieldMap(FieldBase<FieldCollection> & field);
//! Copy constructor
TensorFieldMap(const TensorFieldMap &other) = delete;
//! Move constructor
TensorFieldMap(TensorFieldMap &&other) noexcept = delete;
//! Destructor
virtual ~TensorFieldMap() noexcept = default;
//! Copy assignment operator
TensorFieldMap& operator=(const TensorFieldMap &other) = delete;
//! Move assignment operator
TensorFieldMap& operator=(TensorFieldMap &&other) noexcept = delete;
//! member access
inline value_type operator[](Uint index);
inline value_type operator[](Ccoord ccord);
protected:
private:
};
namespace internal {
/* ---------------------------------------------------------------------- */
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
FieldMap<FieldCollection, T, NbComponents, value_type>::
FieldMap(FieldBase<FieldCollection> & field)
:collection(field.collection), field(field) {
// check type compatibility
if (typeid(T).hash_code() !=
this->field.get_stored_typeid().hash_code()) {
throw FieldInterpretationError
("Cannot create a Map of type '" + typeid(value_type).name() +
"' for a field of type '" +
typeid(this->field.get_stored_typeid()).name());
}
//check size compatibility
if (NbComponents != this->field.get_nb_components()) {
throw FieldInterpretationError
("Cannot create a Map of type '" + typeid(value_type).name() +
"' for a field with " +
std::to_string(this->field.get_nb_components()) + " components");
}
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
// Iterator implementations
//! constructor
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
iterator(Field & field, bool begin)
:collection(field.collection), field(field),
index(begin ? 0 : field.size()) {}
/* ---------------------------------------------------------------------- */
//! constructor for random access
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
iterator(Field & field, Uint index)
:collection(field.collection), field(field),
index(index) {}
/* ---------------------------------------------------------------------- */
//! pre-increment
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
typename FieldMap<FieldCollection, T, NbComponents, value_type>::iterator &
FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator++() {
this->index++;
return *this;
}
/* ---------------------------------------------------------------------- */
//! post-increment
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
typename FieldMap<FieldCollection, T, NbComponents, value_type>::iterator
FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator++(int) {
iterator current = *this;
this->index++;
return current;
}
/* ---------------------------------------------------------------------- */
//! dereference
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
value_type FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator*() const {
return this->field[this->index];
}
/* ---------------------------------------------------------------------- */
//! pre-decrement
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
typename FieldMap<FieldCollection, T, NbComponents, value_type>::iterator &
FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator--() {
this->index--;
return *this;
}
/* ---------------------------------------------------------------------- */
//! post-decrement
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
typename FieldMap<FieldCollection, T, NbComponents, value_type>::iterator
FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator--(int) {
iterator current = *this;
this->index--;
return current;
}
/* ---------------------------------------------------------------------- */
//! Access subscripting
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
value_type FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator[](difference_type diff) {
return this->field[this->index+diff];
}
/* ---------------------------------------------------------------------- */
//! equality
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
bool FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator==(const iterator & other) const {
return this->index == other.index;
}
/* ---------------------------------------------------------------------- */
//! inquality
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
bool FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator==(const iterator & other) const {
return !(*this == other);
}
/* ---------------------------------------------------------------------- */
//! div. comparisons
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
bool FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator<(const iterator & other) const {
return (this->index < other.index);
}
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
bool FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator<=(const iterator & other) const {
return (this->index <= other.index);
}
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
bool FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator>(const iterator & other) const {
return (this->index > other.index);
}
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
bool FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator>=(const iterator & other) const {
return (this->index >= other.index);
}
/* ---------------------------------------------------------------------- */
//! additions, subtractions and corresponding assignments
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
typename FieldMap<FieldCollection, T, NbComponents, value_type>::iterator
FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator+(difference_type diff) const {
return iterator(this->index + diff);
}
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
typename FieldMap<FieldCollection, T, NbComponents, value_type>::iterator
FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator-(difference_type diff) const {
return iterator(this->index - diff);
}
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
typename FieldMap<FieldCollection, T, NbComponents, value_type>::iterator &
FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator+=(difference_type diff) {
this->index += diff;
return *this;
}
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
typename FieldMap<FieldCollection, T, NbComponents, value_type>::iterator &
FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
operator-=(difference_type diff) {
this->index -= diff;
return *this;
}
/* ---------------------------------------------------------------------- */
//! get pixel coordinates
template<class FieldCollection, typename T, size_t NbComponents,
class value_type>
Ccoord FieldMap<FieldCollection, T, NbComponents, value_type>::iterator::
get_ccoord() const {
return this->collection.get_ccoord(this->index);
}
} // internal
/* ---------------------------------------------------------------------- */
template<class FieldCollection, typename T, Dim_t order, Dim_t dim>
TensorFieldMap<FieldCollection, T, order, dim>::
TensorFieldMap(FieldBase<FieldCollection> & field)
:parent(field) {}
/* ---------------------------------------------------------------------- */
//! member access
template<class FieldCollection, typename T, Dim_t order, Dim_t dim>
TensorFieldMap<FieldCollection, T, order, dim>::operator[](Uint index) {
auto && lambda = [&field](auto&&..sizes) {
return value_type(field.data()+NbComponents*index, sizes...);
}
return call_sizes_helper<order, dim>(lambda);
}
template<class FieldCollection, typename T, Dim_t order, Dim_t dim>
TensorFieldMap<FieldCollection, T, order, dim>::operator[](Ccoord ccoord) {
auto && index = this->collection.get_index(ccoord);
auto && lambda = [&field](auto&&..sizes) {
return value_type(field.data()+NbComponents*index, sizes...);
}
return call_sizes_helper<order, dim>(lambda);
}
} // muSpectre
#endif /* FIELD_ITERATOR_H */

Event Timeline