1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
/*
* tensorview_iterator.h
*
* Created on: Dec 28, 2013
* Author: evaleev
*/
#ifndef BTAS_TENSORVIEW_ITERATOR_H_
#define BTAS_TENSORVIEW_ITERATOR_H_
#include <cstddef>
#include <btas/storage_traits.h>
namespace btas {
/// Iterates over elements of \c Storage using ordinal values of indices in \c Range
template <typename Range, typename Storage>
class TensorViewIterator : public std::iterator<typename std::conditional<std::is_const<Storage>::value,
std::forward_iterator_tag,
std::output_iterator_tag>::type,
typename std::conditional<std::is_const<Storage>::value,
const typename storage_traits<Storage>::value_type,
typename storage_traits<Storage>::value_type>::type>
{
struct Enabler {};
public:
typedef Storage storage_type;
typedef std::reference_wrapper<storage_type> storageref_type;
typedef std::reference_wrapper<const storage_type> ncstorageref_type;
typedef std::iterator<typename std::conditional<std::is_const<Storage>::value,
std::forward_iterator_tag,
std::output_iterator_tag>::type,
typename std::conditional<std::is_const<Storage>::value,
const typename storage_traits<Storage>::value_type,
typename storage_traits<Storage>::value_type>::type> base_type;
using typename base_type::value_type;
using typename base_type::pointer;
using typename base_type::reference;
using typename base_type::difference_type;
using typename base_type::iterator_category;
private:
typedef typename Range::ordinal_subiterator subiterator;
typedef typename Range::ordinal_iterator iterator;
typedef typename iterator::value_type ordinal_type;
typedef typename Range::index_type index_type;
public:
/// Default constructor
TensorViewIterator() {}
/// Destructor
~TensorViewIterator() {}
TensorViewIterator(const typename Range::iterator& index_iter,
Storage& storage) :
iter_(subiterator(std::make_pair(*index_iter,index_iter.range()->ordinal(*index_iter)),index_iter.range())),
storageref_(storage) {}
TensorViewIterator(const typename Range::iterator& index_iter,
const storageref_type& storage) :
iter_(subiterator(std::make_pair(*index_iter,index_iter.range()->ordinal(*index_iter)),index_iter.range())),
storageref_(storage) {}
template <typename S = Storage>
TensorViewIterator(const typename Range::iterator& index_iter,
const ncstorageref_type& storage,
typename std::enable_if<std::is_const<S>::value>::type* = 0) :
iter_(subiterator(std::make_pair(*index_iter,index_iter.range()->ordinal(*index_iter)),index_iter.range())),
// standard const_cast cannot "map" const into nontrivial structures, have to reinterpret here
storageref_(reinterpret_cast<const storageref_type&>(storage)) {}
TensorViewIterator(const typename Range::iterator& index_iter,
const ordinal_type& ord,
Storage& storage) :
iter_(subiterator(std::make_pair(*index_iter,ord),index_iter.range())),
storageref_(storage) {}
TensorViewIterator(const iterator& iter,
Storage& storage) :
iter_(iter), storageref_(storage) {}
TensorViewIterator(iterator&& iter,
Storage& storage) :
iter_(iter), storageref_(storage) {}
TensorViewIterator& operator++() {
++iter_;
return *this;
}
const reference operator*() const {
return *(cbegin(storageref_.get()) + *iter_);
}
//template <class = typename std::enable_if<not std::is_const<storage_type>::value,Enabler>::type>
template <typename S = Storage>
typename std::enable_if<not std::is_const<S>::value,reference>::type
operator*() {
return *(begin(storageref_.get()) + *iter_);
}
const index_type& index() const {
return first(*iter_.base());
}
template <typename R, typename S>
friend bool operator==(const TensorViewIterator<R,S>&, const TensorViewIterator<R,S>&);
private:
iterator iter_;
storageref_type storageref_;
};
template <typename Range, typename Storage>
inline bool operator==(const TensorViewIterator<Range,Storage>& i1,
const TensorViewIterator<Range,Storage>& i2) {
return i1.iter_ == i2.iter_;
}
template <typename Range, typename Storage>
inline bool operator!=(const TensorViewIterator<Range,Storage>& i1,
const TensorViewIterator<Range,Storage>& i2) {
return not (i1 == i2);
}
}
#endif /* BTAS_TENSORVIEW_ITERATOR_H_ */
|