xmultiindex_iterator.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTENSOR_XMULTIINDEX_ITERATOR
  10. #define XTENSOR_XMULTIINDEX_ITERATOR
  11. #include "xstrided_view.hpp"
  12. #include "xtl/xsequence.hpp"
  13. namespace xt
  14. {
  15. template <class S>
  16. class xmultiindex_iterator
  17. {
  18. public:
  19. using self_type = xmultiindex_iterator<S>;
  20. using shape_type = S;
  21. using value_type = shape_type;
  22. using reference = value_type&;
  23. using pointer = value_type*;
  24. using difference_type = std::size_t;
  25. using iterator_category = std::forward_iterator_tag;
  26. xmultiindex_iterator() = default;
  27. template <class B, class E, class C>
  28. xmultiindex_iterator(B&& begin, E&& end, C&& current, const std::size_t linear_index)
  29. : m_begin(std::forward<B>(begin))
  30. , m_end(std::forward<E>(end))
  31. , m_current(std::forward<C>(current))
  32. , m_linear_index(linear_index)
  33. {
  34. }
  35. self_type& operator++()
  36. {
  37. std::size_t i = m_begin.size();
  38. while (i != 0)
  39. {
  40. --i;
  41. if (m_current[i] + 1u == m_end[i])
  42. {
  43. m_current[i] = m_begin[i];
  44. }
  45. else
  46. {
  47. m_current[i] += 1;
  48. break;
  49. }
  50. }
  51. m_linear_index++;
  52. return *this;
  53. }
  54. self_type operator++(int)
  55. {
  56. self_type it = *this;
  57. ++(*this);
  58. return it;
  59. }
  60. shape_type& operator*()
  61. {
  62. return m_current;
  63. }
  64. const shape_type& operator*() const
  65. {
  66. return m_current;
  67. }
  68. bool operator==(const self_type& rhs) const
  69. {
  70. return m_linear_index == rhs.m_linear_index;
  71. }
  72. bool operator!=(const self_type& rhs) const
  73. {
  74. return !this->operator==(rhs);
  75. }
  76. private:
  77. shape_type m_begin;
  78. shape_type m_end;
  79. shape_type m_current;
  80. std::size_t m_linear_index{0};
  81. };
  82. template <class S, class B, class E>
  83. auto multiindex_iterator_begin(B&& roi_begin, E&& roi_end)
  84. {
  85. S current;
  86. resize_container(current, roi_begin.size());
  87. std::copy(roi_begin.begin(), roi_begin.end(), current.begin());
  88. return xmultiindex_iterator<S>(std::forward<B>(roi_begin), std::forward<E>(roi_end), std::move(current), 0);
  89. }
  90. template <class S, class B, class E>
  91. auto multiindex_iterator_end(B&& roi_begin, E&& roi_end)
  92. {
  93. S current;
  94. resize_container(current, roi_begin.size());
  95. std::copy(roi_end.begin(), roi_end.end(), current.begin());
  96. std::size_t linear_index = 1;
  97. for (std::size_t i = 0; i < roi_begin.size(); ++i)
  98. {
  99. linear_index *= roi_end[i] - roi_begin[i];
  100. }
  101. return xmultiindex_iterator<S>(
  102. std::forward<B>(roi_begin),
  103. std::forward<E>(roi_end),
  104. std::move(current),
  105. linear_index
  106. );
  107. }
  108. }
  109. #endif