/*************************************************************************** * 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_ITERABLE_HPP #define XTENSOR_ITERABLE_HPP #include "xiterator.hpp" namespace xt { /******************* * xconst_iterable * *******************/ template struct xiterable_inner_types; /** * @class xconst_iterable * @brief Base class for multidimensional iterable constant expressions * * The xconst_iterable class defines the interface for multidimensional * constant expressions that can be iterated. * * @tparam D The derived type, i.e. the inheriting class for which xconst_iterable * provides the interface. */ template class xconst_iterable { public: using derived_type = D; using iterable_types = xiterable_inner_types; using inner_shape_type = typename iterable_types::inner_shape_type; using stepper = typename iterable_types::stepper; using const_stepper = typename iterable_types::const_stepper; template using layout_iterator = xiterator; template using const_layout_iterator = xiterator; template using reverse_layout_iterator = std::reverse_iterator>; template using const_reverse_layout_iterator = std::reverse_iterator>; using linear_iterator = layout_iterator; using const_linear_iterator = const_layout_iterator; using reverse_linear_iterator = reverse_layout_iterator; using const_reverse_linear_iterator = const_reverse_layout_iterator; template using broadcast_iterator = xiterator; template using const_broadcast_iterator = xiterator; template using reverse_broadcast_iterator = std::reverse_iterator>; template using const_reverse_broadcast_iterator = std::reverse_iterator>; using iterator = layout_iterator; using const_iterator = const_layout_iterator; using reverse_iterator = reverse_layout_iterator; using const_reverse_iterator = const_reverse_layout_iterator; template const_layout_iterator begin() const noexcept; template const_layout_iterator end() const noexcept; template const_layout_iterator cbegin() const noexcept; template const_layout_iterator cend() const noexcept; template const_reverse_layout_iterator rbegin() const noexcept; template const_reverse_layout_iterator rend() const noexcept; template const_reverse_layout_iterator crbegin() const noexcept; template const_reverse_layout_iterator crend() const noexcept; template const_broadcast_iterator begin(const S& shape) const noexcept; template const_broadcast_iterator end(const S& shape) const noexcept; template const_broadcast_iterator cbegin(const S& shape) const noexcept; template const_broadcast_iterator cend(const S& shape) const noexcept; template const_reverse_broadcast_iterator rbegin(const S& shape) const noexcept; template const_reverse_broadcast_iterator rend(const S& shape) const noexcept; template const_reverse_broadcast_iterator crbegin(const S& shape) const noexcept; template const_reverse_broadcast_iterator crend(const S& shape) const noexcept; protected: const inner_shape_type& get_shape() const; private: template const_layout_iterator get_cbegin(bool end_index) const noexcept; template const_layout_iterator get_cend(bool end_index) const noexcept; template const_broadcast_iterator get_cbegin(const S& shape, bool end_index) const noexcept; template const_broadcast_iterator get_cend(const S& shape, bool end_index) const noexcept; template const_stepper get_stepper_begin(const S& shape) const noexcept; template const_stepper get_stepper_end(const S& shape, layout_type l) const noexcept; const derived_type& derived_cast() const; }; /************* * xiterable * *************/ /** * @class xiterable * @brief Base class for multidimensional iterable expressions * * The xiterable class defines the interface for multidimensional * expressions that can be iterated. * * @tparam D The derived type, i.e. the inheriting class for which xiterable * provides the interface. */ template class xiterable : public xconst_iterable { public: using derived_type = D; using base_type = xconst_iterable; using inner_shape_type = typename base_type::inner_shape_type; using stepper = typename base_type::stepper; using const_stepper = typename base_type::const_stepper; using linear_iterator = typename base_type::linear_iterator; using reverse_linear_iterator = typename base_type::reverse_linear_iterator; template using layout_iterator = typename base_type::template layout_iterator; template using const_layout_iterator = typename base_type::template const_layout_iterator; template using reverse_layout_iterator = typename base_type::template reverse_layout_iterator; template using const_reverse_layout_iterator = typename base_type::template const_reverse_layout_iterator; template using broadcast_iterator = typename base_type::template broadcast_iterator; template using const_broadcast_iterator = typename base_type::template const_broadcast_iterator; template using reverse_broadcast_iterator = typename base_type::template reverse_broadcast_iterator; template using const_reverse_broadcast_iterator = typename base_type::template const_reverse_broadcast_iterator; using iterator = typename base_type::iterator; using const_iterator = typename base_type::const_iterator; using reverse_iterator = typename base_type::reverse_iterator; using const_reverse_iterator = typename base_type::const_reverse_iterator; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; template layout_iterator begin() noexcept; template layout_iterator end() noexcept; template reverse_layout_iterator rbegin() noexcept; template reverse_layout_iterator rend() noexcept; template broadcast_iterator begin(const S& shape) noexcept; template broadcast_iterator end(const S& shape) noexcept; template reverse_broadcast_iterator rbegin(const S& shape) noexcept; template reverse_broadcast_iterator rend(const S& shape) noexcept; private: template layout_iterator get_begin(bool end_index) noexcept; template layout_iterator get_end(bool end_index) noexcept; template broadcast_iterator get_begin(const S& shape, bool end_index) noexcept; template broadcast_iterator get_end(const S& shape, bool end_index) noexcept; template stepper get_stepper_begin(const S& shape) noexcept; template stepper get_stepper_end(const S& shape, layout_type l) noexcept; template const_stepper get_stepper_begin(const S& shape) const noexcept; template const_stepper get_stepper_end(const S& shape, layout_type l) const noexcept; derived_type& derived_cast(); }; /************************ * xcontiguous_iterable * ************************/ template struct xcontainer_inner_types; namespace detail { template struct get_storage_iterator; template struct get_storage_iterator { using iterator = typename T::const_iterator; using const_iterator = typename T::const_iterator; using reverse_iterator = typename T::const_reverse_iterator; using const_reverse_iterator = typename T::const_reverse_iterator; }; template struct get_storage_iterator { using iterator = typename T::iterator; using const_iterator = typename T::const_iterator; using reverse_iterator = typename T::reverse_iterator; using const_reverse_iterator = typename T::const_reverse_iterator; }; template struct linear_iterator_traits_impl; template struct linear_iterator_traits_impl { using inner_types = xcontainer_inner_types; using storage_type = typename inner_types::storage_type; using iterator_type = get_storage_iterator::value>; using linear_iterator = typename iterator_type::iterator; using const_linear_iterator = typename iterator_type::const_iterator; using reverse_linear_iterator = typename iterator_type::reverse_iterator; using const_reverse_linear_iterator = typename iterator_type::const_reverse_iterator; }; template struct linear_iterator_traits_impl { using inner_types = xcontainer_inner_types; using xexpression_type = typename inner_types::xexpression_type; using linear_iterator = typename xexpression_type::linear_iterator; using const_linear_iterator = typename xexpression_type::const_linear_iterator; using reverse_linear_iterator = typename xexpression_type::reverse_linear_iterator; using const_reverse_linear_iterator = typename xexpression_type::const_reverse_linear_iterator; }; template using linear_iterator_traits = linear_iterator_traits_impl::value>; } /** * @class xcontiguous_iterable * @brief Base class for multidimensional iterable expressions with * contiguous storage * * The xcontiguous_iterable class defines the interface for multidimensional * expressions with contiguous that can be iterated. * * @tparam D The derived type, i.e. the inheriting class for which xcontiguous_iterable * provides the interface. */ template class xcontiguous_iterable : private xiterable { public: using derived_type = D; using inner_types = xcontainer_inner_types; using iterable_base = xiterable; using stepper = typename iterable_base::stepper; using const_stepper = typename iterable_base::const_stepper; static constexpr layout_type static_layout = inner_types::layout; #if defined(_MSC_VER) && _MSC_VER >= 1910 // Workaround for compiler bug in Visual Studio 2017 with respect to alias templates with non-type // parameters. template using layout_iterator = xiterator; template using const_layout_iterator = xiterator< typename iterable_base::const_stepper, typename iterable_base::inner_shape_type*, L>; template using reverse_layout_iterator = std::reverse_iterator>; template using const_reverse_layout_iterator = std::reverse_iterator>; #else template using layout_iterator = typename iterable_base::template layout_iterator; template using const_layout_iterator = typename iterable_base::template const_layout_iterator; template using reverse_layout_iterator = typename iterable_base::template reverse_layout_iterator; template using const_reverse_layout_iterator = typename iterable_base::template const_reverse_layout_iterator; #endif template using broadcast_iterator = typename iterable_base::template broadcast_iterator; template using const_broadcast_iterator = typename iterable_base::template const_broadcast_iterator; template using reverse_broadcast_iterator = typename iterable_base::template reverse_broadcast_iterator; template using const_reverse_broadcast_iterator = typename iterable_base::template const_reverse_broadcast_iterator; using linear_traits = detail::linear_iterator_traits; using linear_iterator = typename linear_traits::linear_iterator; using const_linear_iterator = typename linear_traits::const_linear_iterator; using reverse_linear_iterator = typename linear_traits::reverse_linear_iterator; using const_reverse_linear_iterator = typename linear_traits::const_reverse_linear_iterator; template using select_iterator_impl = std::conditional_t; template using select_iterator = select_iterator_impl>; template using select_const_iterator = select_iterator_impl>; template using select_reverse_iterator = select_iterator_impl>; template using select_const_reverse_iterator = select_iterator_impl< L, const_reverse_linear_iterator, const_reverse_layout_iterator>; using iterator = select_iterator; using const_iterator = select_const_iterator; using reverse_iterator = select_reverse_iterator; using const_reverse_iterator = select_const_reverse_iterator; template select_iterator begin() noexcept; template select_iterator end() noexcept; template select_const_iterator begin() const noexcept; template select_const_iterator end() const noexcept; template select_const_iterator cbegin() const noexcept; template select_const_iterator cend() const noexcept; template select_reverse_iterator rbegin() noexcept; template select_reverse_iterator rend() noexcept; template select_const_reverse_iterator rbegin() const noexcept; template select_const_reverse_iterator rend() const noexcept; template select_const_reverse_iterator crbegin() const noexcept; template select_const_reverse_iterator crend() const noexcept; template broadcast_iterator begin(const S& shape) noexcept; template broadcast_iterator end(const S& shape) noexcept; template const_broadcast_iterator begin(const S& shape) const noexcept; template const_broadcast_iterator end(const S& shape) const noexcept; template const_broadcast_iterator cbegin(const S& shape) const noexcept; template const_broadcast_iterator cend(const S& shape) const noexcept; template reverse_broadcast_iterator rbegin(const S& shape) noexcept; template reverse_broadcast_iterator rend(const S& shape) noexcept; template const_reverse_broadcast_iterator rbegin(const S& shape) const noexcept; template const_reverse_broadcast_iterator rend(const S& shape) const noexcept; template const_reverse_broadcast_iterator crbegin(const S& shape) const noexcept; template const_reverse_broadcast_iterator crend(const S& shape) const noexcept; private: derived_type& derived_cast(); const derived_type& derived_cast() const; friend class xiterable; friend class xconst_iterable; }; /********************************** * xconst_iterable implementation * **********************************/ /** * @name Constant iterators */ //@{ /** * Returns a constant iterator to the first element of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::begin() const noexcept -> const_layout_iterator { return this->template cbegin(); } /** * Returns a constant iterator to the element following the last element * of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::end() const noexcept -> const_layout_iterator { return this->template cend(); } /** * Returns a constant iterator to the first element of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::cbegin() const noexcept -> const_layout_iterator { return this->template get_cbegin(false); } /** * Returns a constant iterator to the element following the last element * of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::cend() const noexcept -> const_layout_iterator { return this->template get_cend(true); } //@} /** * @name Constant reverse iterators */ //@{ /** * Returns a constant iterator to the first element of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::rbegin() const noexcept -> const_reverse_layout_iterator { return this->template crbegin(); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::rend() const noexcept -> const_reverse_layout_iterator { return this->template crend(); } /** * Returns a constant iterator to the first element of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::crbegin() const noexcept -> const_reverse_layout_iterator { return const_reverse_layout_iterator(get_cend(true)); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::crend() const noexcept -> const_reverse_layout_iterator { return const_reverse_layout_iterator(get_cbegin(false)); } //@} /** * @name Constant broadcast iterators */ //@{ /** * Returns a constant iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::begin(const S& shape) const noexcept -> const_broadcast_iterator { return cbegin(shape); } /** * Returns a constant iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::end(const S& shape) const noexcept -> const_broadcast_iterator { return cend(shape); } /** * Returns a constant iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::cbegin(const S& shape) const noexcept -> const_broadcast_iterator { return get_cbegin(shape, false); } /** * Returns a constant iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::cend(const S& shape) const noexcept -> const_broadcast_iterator { return get_cend(shape, true); } //@} /** * @name Constant reverse broadcast iterators */ //@{ /** * Returns a constant iterator to the first element of the reversed expression. * The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::rbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator { return crbegin(shape); } /** * Returns a constant iterator to the element following the last element of the * reversed expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::rend(const S& shape) const noexcept -> const_reverse_broadcast_iterator { return crend(shape); } /** * Returns a constant iterator to the first element of the reversed expression. * The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::crbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator { return const_reverse_broadcast_iterator(get_cend(shape, true)); } /** * Returns a constant iterator to the element following the last element of the * reversed expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xconst_iterable::crend(const S& shape) const noexcept -> const_reverse_broadcast_iterator { return const_reverse_broadcast_iterator(get_cbegin(shape, false)); } //@} template template inline auto xconst_iterable::get_cbegin(bool end_index) const noexcept -> const_layout_iterator { return const_layout_iterator(get_stepper_begin(get_shape()), &get_shape(), end_index); } template template inline auto xconst_iterable::get_cend(bool end_index) const noexcept -> const_layout_iterator { return const_layout_iterator(get_stepper_end(get_shape(), L), &get_shape(), end_index); } template template inline auto xconst_iterable::get_cbegin(const S& shape, bool end_index) const noexcept -> const_broadcast_iterator { return const_broadcast_iterator(get_stepper_begin(shape), shape, end_index); } template template inline auto xconst_iterable::get_cend(const S& shape, bool end_index) const noexcept -> const_broadcast_iterator { return const_broadcast_iterator(get_stepper_end(shape, L), shape, end_index); } template template inline auto xconst_iterable::get_stepper_begin(const S& shape) const noexcept -> const_stepper { return derived_cast().stepper_begin(shape); } template template inline auto xconst_iterable::get_stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper { return derived_cast().stepper_end(shape, l); } template inline auto xconst_iterable::get_shape() const -> const inner_shape_type& { return derived_cast().shape(); } template inline auto xconst_iterable::derived_cast() const -> const derived_type& { return *static_cast(this); } /**************************** * xiterable implementation * ****************************/ /** * @name Iterators */ //@{ /** * Returns an iterator to the first element of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xiterable::begin() noexcept -> layout_iterator { return get_begin(false); } /** * Returns an iterator to the element following the last element * of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xiterable::end() noexcept -> layout_iterator { return get_end(true); } //@} /** * @name Reverse iterators */ //@{ /** * Returns an iterator to the first element of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xiterable::rbegin() noexcept -> reverse_layout_iterator { return reverse_layout_iterator(get_end(true)); } /** * Returns an iterator to the element following the last element * of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xiterable::rend() noexcept -> reverse_layout_iterator { return reverse_layout_iterator(get_begin(false)); } //@} /** * @name Broadcast iterators */ //@{ /** * Returns an iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xiterable::begin(const S& shape) noexcept -> broadcast_iterator { return get_begin(shape, false); } /** * Returns an iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xiterable::end(const S& shape) noexcept -> broadcast_iterator { return get_end(shape, true); } //@} /** * @name Reverse broadcast iterators */ //@{ /** * Returns an iterator to the first element of the reversed expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xiterable::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator { return reverse_broadcast_iterator(get_end(shape, true)); } /** * Returns an iterator to the element following the last element of the * reversed expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xiterable::rend(const S& shape) noexcept -> reverse_broadcast_iterator { return reverse_broadcast_iterator(get_begin(shape, false)); } //@} template template inline auto xiterable::get_begin(bool end_index) noexcept -> layout_iterator { return layout_iterator(get_stepper_begin(this->get_shape()), &(this->get_shape()), end_index); } template template inline auto xiterable::get_end(bool end_index) noexcept -> layout_iterator { return layout_iterator(get_stepper_end(this->get_shape(), L), &(this->get_shape()), end_index); } template template inline auto xiterable::get_begin(const S& shape, bool end_index) noexcept -> broadcast_iterator { return broadcast_iterator(get_stepper_begin(shape), shape, end_index); } template template inline auto xiterable::get_end(const S& shape, bool end_index) noexcept -> broadcast_iterator { return broadcast_iterator(get_stepper_end(shape, L), shape, end_index); } template template inline auto xiterable::get_stepper_begin(const S& shape) noexcept -> stepper { return derived_cast().stepper_begin(shape); } template template inline auto xiterable::get_stepper_end(const S& shape, layout_type l) noexcept -> stepper { return derived_cast().stepper_end(shape, l); } template template inline auto xiterable::get_stepper_begin(const S& shape) const noexcept -> const_stepper { return derived_cast().stepper_begin(shape); } template template inline auto xiterable::get_stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper { return derived_cast().stepper_end(shape, l); } template inline auto xiterable::derived_cast() -> derived_type& { return *static_cast(this); } /*************************************** * xcontiguous_iterable implementation * ***************************************/ /** * @name Iterators */ //@{ /** * Returns an iterator to the first element of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::begin() noexcept -> select_iterator { return xtl::mpl::static_if( [&](auto self) { return self(*this).derived_cast().linear_begin(); }, /*else*/ [&](auto self) { return self(*this).iterable_base::template begin(); } ); } /** * Returns an iterator to the element following the last element * of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::end() noexcept -> select_iterator { return xtl::mpl::static_if( [&](auto self) { return self(*this).derived_cast().linear_end(); }, /*else*/ [&](auto self) { return self(*this).iterable_base::template end(); } ); } /** * Returns a constant iterator to the first element of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::begin() const noexcept -> select_const_iterator { return this->template cbegin(); } /** * Returns a constant iterator to the element following the last element * of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::end() const noexcept -> select_const_iterator { return this->template cend(); } /** * Returns a constant iterator to the first element of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::cbegin() const noexcept -> select_const_iterator { return xtl::mpl::static_if( [&](auto self) { return self(*this).derived_cast().linear_cbegin(); }, /*else*/ [&](auto self) { return self(*this).iterable_base::template cbegin(); } ); } /** * Returns a constant iterator to the element following the last element * of the expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::cend() const noexcept -> select_const_iterator { return xtl::mpl::static_if( [&](auto self) { return self(*this).derived_cast().linear_cend(); }, /*else*/ [&](auto self) { return self(*this).iterable_base::template cend(); } ); } //@} /** * @name Reverse iterators */ //@{ /** * Returns an iterator to the first element of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::rbegin() noexcept -> select_reverse_iterator { return xtl::mpl::static_if( [&](auto self) { return self(*this).derived_cast().linear_rbegin(); }, /*else*/ [&](auto self) { return self(*this).iterable_base::template rbegin(); } ); } /** * Returns an iterator to the element following the last element * of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::rend() noexcept -> select_reverse_iterator { return xtl::mpl::static_if( [&](auto self) { return self(*this).derived_cast().linear_rend(); }, /*else*/ [&](auto self) { return self(*this).iterable_base::template rend(); } ); } /** * Returns a constant iterator to the first element of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::rbegin() const noexcept -> select_const_reverse_iterator { return this->template crbegin(); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::rend() const noexcept -> select_const_reverse_iterator { return this->template crend(); } /** * Returns a constant iterator to the first element of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::crbegin() const noexcept -> select_const_reverse_iterator { return xtl::mpl::static_if( [&](auto self) { return self(*this).derived_cast().linear_crbegin(); }, /*else*/ [&](auto self) { return self(*this).iterable_base::template crbegin(); } ); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::crend() const noexcept -> select_const_reverse_iterator { return xtl::mpl::static_if( [&](auto self) { return self(*this).derived_cast().linear_crend(); }, /*else*/ [&](auto self) { return self(*this).iterable_base::template crend(); } ); } //@} /** * @name Broadcast iterators */ /** * Returns an iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ //@{ template template inline auto xcontiguous_iterable::begin(const S& shape) noexcept -> broadcast_iterator { return iterable_base::template begin(shape); } /** * Returns an iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::end(const S& shape) noexcept -> broadcast_iterator { return iterable_base::template end(shape); } /** * Returns a constant iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::begin(const S& shape) const noexcept -> const_broadcast_iterator { return iterable_base::template begin(shape); } /** * Returns a constant iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::end(const S& shape) const noexcept -> const_broadcast_iterator { return iterable_base::template end(shape); } /** * Returns a constant iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::cbegin(const S& shape) const noexcept -> const_broadcast_iterator { return iterable_base::template cbegin(shape); } /** * Returns a constant iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::cend(const S& shape) const noexcept -> const_broadcast_iterator { return iterable_base::template cend(shape); } //@} /** * @name Reverse broadcast iterators */ //@{ /** * Returns an iterator to the first element of the reversed expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator { return iterable_base::template rbegin(shape); } /** * Returns an iterator to the element following the last element of the * reversed expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::rend(const S& shape) noexcept -> reverse_broadcast_iterator { return iterable_base::template rend(shape); } /** * Returns a constant iterator to the first element of the reversed expression. * The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::rbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator { return iterable_base::template rbegin(shape); } /** * Returns a constant iterator to the element following the last element of the * reversed expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::rend(const S& shape) const noexcept -> const_reverse_broadcast_iterator { return iterable_base::template rend(shape); } /** * Returns a constant iterator to the first element of the reversed expression. * The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::crbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator { return iterable_base::template crbegin(shape); } /** * Returns a constant iterator to the element following the last element of the * reversed expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL. */ template template inline auto xcontiguous_iterable::crend(const S& shape) const noexcept -> const_reverse_broadcast_iterator { return iterable_base::template crend(shape); } //@} template inline auto xcontiguous_iterable::derived_cast() -> derived_type& { return *static_cast(this); } template inline auto xcontiguous_iterable::derived_cast() const -> const derived_type& { return *static_cast(this); } } #endif