/*************************************************************************** * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * Copyright (c) QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XTENSOR_XMULTIINDEX_ITERATOR #define XTENSOR_XMULTIINDEX_ITERATOR #include "xstrided_view.hpp" #include "xtl/xsequence.hpp" namespace xt { template class xmultiindex_iterator { public: using self_type = xmultiindex_iterator; using shape_type = S; using value_type = shape_type; using reference = value_type&; using pointer = value_type*; using difference_type = std::size_t; using iterator_category = std::forward_iterator_tag; xmultiindex_iterator() = default; template xmultiindex_iterator(B&& begin, E&& end, C&& current, const std::size_t linear_index) : m_begin(std::forward(begin)) , m_end(std::forward(end)) , m_current(std::forward(current)) , m_linear_index(linear_index) { } self_type& operator++() { std::size_t i = m_begin.size(); while (i != 0) { --i; if (m_current[i] + 1u == m_end[i]) { m_current[i] = m_begin[i]; } else { m_current[i] += 1; break; } } m_linear_index++; return *this; } self_type operator++(int) { self_type it = *this; ++(*this); return it; } shape_type& operator*() { return m_current; } const shape_type& operator*() const { return m_current; } bool operator==(const self_type& rhs) const { return m_linear_index == rhs.m_linear_index; } bool operator!=(const self_type& rhs) const { return !this->operator==(rhs); } private: shape_type m_begin; shape_type m_end; shape_type m_current; std::size_t m_linear_index{0}; }; template auto multiindex_iterator_begin(B&& roi_begin, E&& roi_end) { S current; resize_container(current, roi_begin.size()); std::copy(roi_begin.begin(), roi_begin.end(), current.begin()); return xmultiindex_iterator(std::forward(roi_begin), std::forward(roi_end), std::move(current), 0); } template auto multiindex_iterator_end(B&& roi_begin, E&& roi_end) { S current; resize_container(current, roi_begin.size()); std::copy(roi_end.begin(), roi_end.end(), current.begin()); std::size_t linear_index = 1; for (std::size_t i = 0; i < roi_begin.size(); ++i) { linear_index *= roi_end[i] - roi_begin[i]; } return xmultiindex_iterator( std::forward(roi_begin), std::forward(roi_end), std::move(current), linear_index ); } } #endif