28#ifndef REMORA_DETAIL_ITERATOR_HPP
29#define REMORA_DETAIL_ITERATOR_HPP
37#include "../detail/check.hpp"
39namespace remora{
namespace iterators{
42struct sparse_random_access_iterator_tag:
public std::random_access_iterator_tag{};
43struct packed_random_access_iterator_tag:
public std::random_access_iterator_tag{};
44struct dense_random_access_iterator_tag:
public packed_random_access_iterator_tag{};
57template<
class I,
class T,
class Tag>
58struct random_access_iterator_base
59:
public std::iterator<Tag, T> {
60 typedef I derived_iterator_type;
61 typedef T derived_value_type;
62 typedef std::ptrdiff_t difference_type;
64 friend I operator + (random_access_iterator_base
const& it, difference_type n) {
65 I tmp(
static_cast<const I&
>(it));
68 friend I operator - (random_access_iterator_base
const& it, difference_type n) {
69 I tmp(
static_cast<const I&
>(it));
73 friend I operator + (difference_type n, random_access_iterator_base
const& it) {
74 I tmp(
static_cast<const I&
>(it));
77 friend I operator - (difference_type n, random_access_iterator_base
const& it) {
78 I tmp(
static_cast<const I&
>(it));
83template<
class I,
class T,
class Tag>
84I operator ++ (random_access_iterator_base<I,T,Tag>& it,
int) {
85 I& d =
static_cast<I&
>(it);
91template<
class I,
class T,
class Tag>
92I operator -- (random_access_iterator_base<I,T,Tag>& it,
int) {
93 I& d =
static_cast<I&
>(it);
101template<
class I1,
class T1,
class I2,
class T2,
class Tag>
103 random_access_iterator_base<I1,T1,Tag>
const& it1,
104 random_access_iterator_base<I2,T2,Tag>
const& it2
106 I1
const& d1 =
static_cast<const I1&
>(it1);
107 I2
const& d2 =
static_cast<const I2&
>(it2);
111template<
class I1,
class T1,
class I2,
class T2,
class Tag>
113 random_access_iterator_base<I1,T1,Tag>
const& it1,
114 random_access_iterator_base<I2,T2,Tag>
const& it2
116 I1
const& d1 =
static_cast<const I1&
>(it1);
117 I2
const& d2 =
static_cast<const I2&
>(it2);
121template<
class I1,
class T1,
class I2,
class T2,
class Tag>
123 random_access_iterator_base<I1,T1,Tag>
const& it1,
124 random_access_iterator_base<I2,T2,Tag>
const& it2
126 I1
const& d1 =
static_cast<const I1&
>(it1);
127 I2
const& d2 =
static_cast<const I2&
>(it2);
131template<
class I1,
class T1,
class I2,
class T2,
class Tag>
133 random_access_iterator_base<I1,T1,Tag>
const& it1,
134 random_access_iterator_base<I2,T2,Tag>
const& it2
136 I1
const& d1 =
static_cast<const I1&
>(it1);
137 I2
const& d2 =
static_cast<const I2&
>(it2);
143template<
class Closure>
144class indexed_iterator:
145 public random_access_iterator_base<
146 indexed_iterator<Closure>,
147 typename Closure::value_type,
148 dense_random_access_iterator_tag
151 typedef std::size_t size_type;
152 typedef std::ptrdiff_t difference_type;
153 typedef typename Closure::value_type value_type;
154 typedef typename std::conditional<
155 std::is_const<Closure>::value,
156 typename Closure::const_reference,
157 typename Closure::reference
162 indexed_iterator(Closure container, size_type index)
163 : m_index(index), m_closure(container) {}
166 indexed_iterator(indexed_iterator<C>
const& iterator)
167 : m_index(iterator.m_index), m_closure(iterator.m_closure) {}
170 indexed_iterator& operator++() {
174 indexed_iterator& operator--() {
178 indexed_iterator& operator += (difference_type n) {
182 indexed_iterator& operator -= (difference_type n) {
187 difference_type operator - (indexed_iterator<T>
const& it)
const {
188 return m_index - it.m_index;
192 reference operator *()
const {
193 REMORA_RANGE_CHECK(m_index < m_closure.size());
194 return m_closure(m_index);
196 reference operator [](difference_type n)
const {
197 REMORA_RANGE_CHECK(m_index+n < m_closure.size());
198 return m_closure(m_index+n);
202 size_type index()
const {
208 indexed_iterator &operator = (indexed_iterator<T>
const& it) {
209 m_closure = it.m_closure;
210 m_index = it.m_index;
216 bool operator == (indexed_iterator<T>
const& it)
const {
217 return m_index == it.m_index;
220 bool operator < (indexed_iterator<T>
const& it)
const {
221 return m_index < it.m_index;
227 template<
class>
friend class indexed_iterator;
230template<
class T,
class Tag=dense_random_access_iterator_tag>
231class dense_storage_iterator:
232public random_access_iterator_base<
233 dense_storage_iterator<T,Tag>,
234 typename std::remove_const<T>::type,
238 typedef std::size_t size_type;
239 typedef std::ptrdiff_t difference_type;
240 typedef typename std::remove_const<T>::type value_type;
241 typedef T& reference;
245 dense_storage_iterator():m_pos(0),m_index(0) {}
246 dense_storage_iterator(pointer pos, size_type index, difference_type stride = 1)
247 :m_pos(pos), m_index(index), m_stride(stride) {}
250 dense_storage_iterator(dense_storage_iterator<U,Tag>
const& iter)
251 :m_pos(iter.m_pos), m_index(iter.m_index), m_stride(iter.m_stride){}
254 dense_storage_iterator& operator=(dense_storage_iterator<U,Tag>
const& iter){
256 m_index = iter.m_index;
257 m_stride = iter.m_stride;
262 dense_storage_iterator& operator ++ () {
267 dense_storage_iterator& operator -- () {
272 dense_storage_iterator& operator += (difference_type n) {
277 dense_storage_iterator& operator -= (difference_type n) {
283 difference_type operator - (dense_storage_iterator<U,Tag>
const& it)
const {
285 return (difference_type)m_index - (difference_type)it.m_index;
289 reference operator*()
const {
292 reference operator [](difference_type n)
const {
293 return m_pos[m_stride*n];
297 size_type index()
const {
303 bool operator == (dense_storage_iterator<U,Tag>
const& it)
const {
306 return m_index == it.m_index;
309 bool operator < (dense_storage_iterator<U,Tag>
const& it)
const {
311 return m_index < it.m_index;
317 difference_type m_stride;
318 template<
class,
class>
friend class dense_storage_iterator;
320template<
class T,
class I>
321class compressed_storage_iterator:
322public random_access_iterator_base<
323 compressed_storage_iterator<T,I>,
324 typename std::remove_const<T>::type,
325 sparse_random_access_iterator_tag
328 typedef typename std::remove_const<T>::type value_type;
329 typedef typename std::remove_const<I>::type size_type;
330 typedef std::ptrdiff_t difference_type;
331 typedef T& reference;
335 compressed_storage_iterator() {}
336 compressed_storage_iterator(
337 T* value_array, I* index_array,
338 size_type position, size_type major_pos = 0
340 : m_values(value_array),m_indices(index_array)
341 , m_position(position), m_major_pos(major_pos){}
343 template<
class U,
class V>
344 compressed_storage_iterator(compressed_storage_iterator<U,V>
const& it) {
345 m_position = it.m_position;
346 m_major_pos = it.m_major_pos;
347 m_values = it.m_values;
348 m_indices = it.m_indices;
351 template<
class U,
class V>
352 compressed_storage_iterator &operator = (compressed_storage_iterator<U,V>
const& it) {
353 m_position = it.m_position;
354 m_major_pos = it.m_major_pos;
355 m_values = it.m_values;
356 m_indices = it.m_indices;
361 compressed_storage_iterator &operator++ () {
365 compressed_storage_iterator &operator -- () {
366 REMORA_RANGE_CHECK(m_position > 0);
371 compressed_storage_iterator &operator += (difference_type n) {
375 compressed_storage_iterator &operator -= (difference_type n) {
381 reference operator* ()
const {
382 return m_values[m_position];
384 reference operator [](difference_type n)
const {
385 return m_values[m_position+n];
387 size_type index()
const {
388 return m_indices[m_position];
391 template<
class U,
class V>
392 difference_type operator - (compressed_storage_iterator<U,V>
const& it)
const {
393 REMORA_RANGE_CHECK(m_values == it.m_values);
394 REMORA_RANGE_CHECK(m_indices == it.m_indices);
395 return difference_type(m_position) - difference_type(it.m_position);
398 size_type major_index()
const{
402 template<
class U,
class V>
403 bool operator == (compressed_storage_iterator<U,V>
const &it)
const {
404 REMORA_RANGE_CHECK(m_values == it.m_values);
405 REMORA_RANGE_CHECK(m_indices == it.m_indices);
406 return m_position == it.m_position;
412 std::size_t m_position;
413 std::size_t m_major_pos;
414 template<
class,
class>
friend class compressed_storage_iterator;
420class constant_iterator:
421public random_access_iterator_base<
422 constant_iterator<T>,
423 typename std::remove_const<T>::type,
424 dense_random_access_iterator_tag
427 typedef std::size_t size_type;
428 typedef std::ptrdiff_t difference_type;
429 typedef T value_type;
430 typedef value_type
const &reference;
431 typedef value_type
const *pointer;
434 constant_iterator() {}
435 constant_iterator(value_type value, size_type position)
436 :m_position(position),m_value(value) {}
439 constant_iterator &operator ++ () {
443 constant_iterator &operator -- () {
447 constant_iterator &operator += (difference_type n) {
451 constant_iterator &operator -= (difference_type n) {
455 difference_type operator - (constant_iterator
const &it)
const {
456 return m_position - it.m_position;
460 reference operator * ()
const {
463 reference operator [](difference_type n)
const {
468 size_type index()
const {
474 constant_iterator &operator = (constant_iterator
const &it) {
475 m_position = it.m_position;
476 m_value = it.m_value;
481 bool operator == (constant_iterator
const &it)
const {
482 return m_position == it.m_position;
484 bool operator < (constant_iterator
const &it)
const {
485 return m_position < it.m_position;
488 size_type m_position;
492template<
class BaseIterator,
class F>
493class transform_iterator:
494public random_access_iterator_base<
495 transform_iterator<BaseIterator,F>,
496 typename BaseIterator::value_type,
497 typename BaseIterator::iterator_category
500 typedef typename BaseIterator::iterator_category iterator_category;
501 typedef std::size_t size_type;
502 typedef std::ptrdiff_t difference_type;
503 typedef typename std::result_of<F(
typename BaseIterator::value_type)>::type value_type;
504 typedef value_type reference;
505 typedef value_type *pointer;
508 transform_iterator() {}
509 transform_iterator(BaseIterator
const &it,F functor)
510 :m_position(it),m_functor(functor) {}
513 transform_iterator &operator ++ () {
517 transform_iterator &operator -- () {
521 transform_iterator &operator += (difference_type n) {
525 transform_iterator &operator -= (difference_type n) {
529 difference_type operator - (transform_iterator
const &it)
const {
530 return m_position - it.m_position;
534 reference operator * ()
const {
535 return m_functor(*m_position);
537 reference operator [](difference_type n)
const {
542 size_type index()
const {
543 return m_position.index();
548 transform_iterator &operator = (transform_iterator<Iter,F>
const &it) {
549 m_position = it.m_position;
550 m_functor = it.m_functor;
555 bool operator == (transform_iterator
const &it)
const {
556 return m_position == it.m_position;
558 bool operator < (transform_iterator
const &it)
const {
559 return m_position < it.m_position;
563 BaseIterator m_position;
568class one_hot_iterator:
public random_access_iterator_base<
569 one_hot_iterator<T>, T, sparse_random_access_iterator_tag
572 typedef T value_type;
573 typedef std::ptrdiff_t difference_type;
574 typedef std::size_t size_type;
575 typedef T& reference;
576 typedef T
const& const_reference;
577 typedef value_type
const* pointer;
581 one_hot_iterator(size_type index, value_type value,
bool isEnd)
582 :m_index(index),m_value(value),m_isEnd(isEnd){}
585 one_hot_iterator& operator ++ () {
589 one_hot_iterator& operator -- () {
593 one_hot_iterator &operator += (difference_type n) {
597 one_hot_iterator &operator -= (difference_type n) {
604 reference operator*()
const {
609 size_type index()
const{
612 difference_type operator - (one_hot_iterator
const &it)
const {
613 return m_isEnd - it.m_isEnd;
617 one_hot_iterator& operator = (one_hot_iterator
const& it) {
618 m_index = it.m_index;
619 m_value = it.m_value;
624 bool operator == (one_hot_iterator
const& it)
const {
625 REMORA_RANGE_CHECK(m_index == it.m_index);
626 return m_isEnd == it.m_isEnd;
628 bool operator < (one_hot_iterator
const &it)
const {
629 return m_isEnd < it.m_isEnd;
639template<
class I1,
class I2>
640struct iterator_restrict_traits {
641 typedef I1 iterator_category;
645struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_random_access_iterator_tag> {
646 typedef sparse_random_access_iterator_tag iterator_category;
650struct iterator_restrict_traits<packed_random_access_iterator_tag,dense_random_access_iterator_tag> {
651 typedef dense_random_access_iterator_tag iterator_category;
655struct iterator_restrict_traits<packed_random_access_iterator_tag,sparse_random_access_iterator_tag> {
656 typedef sparse_random_access_iterator_tag iterator_category;
659template<
class Iterator1,
class Iterator2,
class F>
660class binary_transform_iterator:
661public random_access_iterator_base<
662 binary_transform_iterator<Iterator1,Iterator2,F>,
663 typename std::result_of<F(typename Iterator1::value_type, typename Iterator2::value_type)>::type,
664 typename iterator_restrict_traits<
665 typename Iterator1::iterator_category,
666 typename Iterator2::iterator_category
670 typedef typename Iterator1::iterator_category category1;
671 typedef typename Iterator2::iterator_category category2;
673 typedef typename iterator_restrict_traits<
676 >::iterator_category iterator_category;
677 typedef std::size_t size_type;
678 typedef std::ptrdiff_t difference_type;
679 typedef typename std::result_of<F(
typename Iterator1::value_type,
typename Iterator2::value_type)>::type value_type;
680 typedef value_type reference;
681 typedef value_type *pointer;
684 binary_transform_iterator() {}
685 binary_transform_iterator(
687 Iterator1
const &it1, Iterator1
const &end1,
688 Iterator2
const &it2, Iterator2
const &end2
690 , m_iterator1(it1), m_end1(end1)
691 , m_iterator2(it2), m_end2(end2)
695 ensureValidPosition(category1(),category2());
698 if(m_iterator1 != end1 && m_iterator2 != end2)
699 m_index = std::min(m_iterator1.index(),m_iterator2.index());
708 void ensureValidPosition(
709 dense_random_access_iterator_tag,
710 dense_random_access_iterator_tag
713 dense_random_access_iterator_tag,
714 dense_random_access_iterator_tag
721 dense_random_access_iterator_tag,
722 dense_random_access_iterator_tag
729 dense_random_access_iterator_tag,
730 dense_random_access_iterator_tag,
737 value_type dereference(
738 dense_random_access_iterator_tag,
739 dense_random_access_iterator_tag
741 return m_functor(*m_iterator1, *m_iterator2);
745 void ensureValidPosition(
746 sparse_random_access_iterator_tag,
747 sparse_random_access_iterator_tag
750 if(F::left_zero_remains || F::right_zero_remains){
752 m_iterator1 != m_end1 && m_iterator2 != m_end2
753 && m_iterator1.index() != m_iterator2.index()
755 if(m_iterator1.index() < m_iterator2.index())
760 if( m_iterator1 == m_end1 || m_iterator2 == m_end2){
761 m_iterator2 = m_end2;
762 m_iterator1 = m_end1;
767 sparse_random_access_iterator_tag,
768 sparse_random_access_iterator_tag
770 if(F::left_zero_remains || F::right_zero_remains){
773 ensureValidPosition(category1(),category2());
775 if (m_iterator1 != m_end1 && m_iterator2 != m_end2){
776 if( m_iterator1.index() == m_iterator2.index()){
780 else if(m_iterator1.index() < m_iterator2.index())
784 }
else if(m_iterator1 != m_end1){
790 size_type index1 = std::numeric_limits<size_type>::max();
791 size_type index2 = std::numeric_limits<size_type>::max();
792 if(m_iterator1 != m_end1)
793 index1 = m_iterator1.index();
794 if(m_iterator2 != m_end2)
795 index2 = m_iterator2.index();
797 m_index = std::min(index1, index2);
800 sparse_random_access_iterator_tag,
801 sparse_random_access_iterator_tag
803 if (m_index <= m_iterator1.index())
805 if (m_index <= m_iterator2.index())
807 m_index = std::max(m_iterator1.index(), m_iterator2.index());
810 sparse_random_access_iterator_tag,
811 sparse_random_access_iterator_tag,
815 increment(category1(),category2());
819 decrement(category1(),category2());
823 value_type dereference(
824 sparse_random_access_iterator_tag,
825 sparse_random_access_iterator_tag
827 value_type t1 = value_type();
828 if (m_iterator1 != m_end1 && m_iterator1.index() == m_index)
830 value_type t2 = value_type();
831 if (m_iterator2 != m_end2 && m_iterator2.index() == m_index)
833 return m_functor(t1, t2);
838 void ensureValidPosition(
839 dense_random_access_iterator_tag,
840 sparse_random_access_iterator_tag
842 if(F::right_zero_remains){
843 m_iterator1 += m_iterator2.index()-m_iterator1.index();
848 dense_random_access_iterator_tag,
849 sparse_random_access_iterator_tag
851 if(F::right_zero_remains){
853 m_iterator1 += m_iterator2.index()-m_iterator1.index();
855 if (m_iterator2 != m_end2){
856 if( m_iterator1.index() == m_iterator2.index()){
860 else if(m_iterator2.index() > m_iterator1.index())
867 size_type index1 = m_iterator1.index();
868 size_type index2 = std::numeric_limits<size_type>::max();
869 if(m_iterator2 != m_end2)
870 index2 = m_iterator2.index();
871 m_index = std::min(index1, index2);
874 dense_random_access_iterator_tag,
875 sparse_random_access_iterator_tag
877 if(F::right_zero_remains){
879 m_iterator1 -= m_iterator1.index()-m_iterator2.index();
881 if (m_index <= m_iterator1.index())
883 if (m_index <= m_iterator2.index())
885 m_index = std::max(m_iterator1.index(), m_iterator2.index());
889 dense_random_access_iterator_tag,
890 sparse_random_access_iterator_tag,
894 increment(category1(),category2());
898 decrement(category1(),category2());
902 value_type dereference(
903 dense_random_access_iterator_tag,
904 sparse_random_access_iterator_tag
906 typedef typename Iterator2::value_type value_type2;
907 value_type t2 = value_type2();
908 if (m_iterator2 != m_end2 && m_iterator2.index() == m_index)
910 return m_functor(*m_iterator1, t2);
914 void ensureValidPosition(
915 sparse_random_access_iterator_tag,
916 dense_random_access_iterator_tag
918 if(F::left_zero_remains){
919 m_iterator2 += m_iterator1.index()-m_iterator2.index();
923 sparse_random_access_iterator_tag,
924 dense_random_access_iterator_tag
926 if(F::left_zero_remains){
928 m_iterator2 += m_iterator1.index()-m_iterator2.index();
930 if (m_iterator1 != m_end1){
931 if( m_iterator1.index() == m_iterator2.index()){
935 else if(m_iterator1.index() > m_iterator2.index())
942 size_type index1 = std::numeric_limits<size_type>::max();
943 size_type index2 = m_iterator2.index();
944 if(m_iterator1 != m_end1)
945 index1 = m_iterator1.index();
946 m_index = std::min(index1, index2);
949 sparse_random_access_iterator_tag,
950 dense_random_access_iterator_tag
952 if(F::left_zero_remains){
954 m_iterator2 -= m_iterator2.index()-m_iterator1.index();
956 if (m_index <= m_iterator2.index())
958 if (m_index <= m_iterator1.index())
960 m_index = std::max(m_iterator1.index(), m_iterator2.index());
964 sparse_random_access_iterator_tag,
965 dense_random_access_iterator_tag,
969 increment(category1(),category2());
973 decrement(category1(),category2());
977 value_type dereference(
978 sparse_random_access_iterator_tag,
979 dense_random_access_iterator_tag
981 typedef typename Iterator1::value_type value_type1;
982 value_type t1 = value_type1();
983 if (m_iterator1 != m_end1 && m_iterator1.index() == m_index)
985 return m_functor(t1,*m_iterator2);
990 binary_transform_iterator &operator ++ () {
991 increment(category1(),category2());
994 binary_transform_iterator &operator -- () {
995 decrement(category1(),category2());
998 binary_transform_iterator &operator += (difference_type n) {
999 increment(category1(),category2(), n);
1002 binary_transform_iterator &operator -= (difference_type n) {
1003 increment(category1(),category2(), -n);
1006 difference_type operator - (
const binary_transform_iterator &it)
const {
1007 difference_type diff1 = m_iterator1- it.m_iterator1;
1008 difference_type diff2 = m_iterator2- it.m_iterator2;
1009 return std::abs(diff1) > std::abs(diff2)? diff1:diff2;
1013 reference operator * ()
const {
1014 return dereference(category1(),category2());
1016 reference operator [](difference_type n)
const {
1017 return *(*
this + n);
1021 size_type index()
const {
1026 bool operator == (binary_transform_iterator
const &it)
const {
1027 return m_iterator1 == it.m_iterator1 && m_iterator2 == it.m_iterator2;
1029 bool operator < (binary_transform_iterator
const &it)
const {
1030 return m_iterator1 < it.m_iterator1 || m_iterator2 < it.m_iterator2;
1034 Iterator1 m_iterator1;
1036 Iterator2 m_iterator2;