From 1198e844d0e524e66b02fcae2f27d6a7f4740be0 Mon Sep 17 00:00:00 2001 From: Sylvain Corlay Date: Wed, 6 Sep 2017 11:44:09 +0200 Subject: [PATCH] Enabling iterator pairs on pyarray backstrides --- include/xtensor-python/pyarray.hpp | 211 ++++++++++++++++++- include/xtensor-python/pystrides_adaptor.hpp | 51 +++-- 2 files changed, 248 insertions(+), 14 deletions(-) diff --git a/include/xtensor-python/pyarray.hpp b/include/xtensor-python/pyarray.hpp index 2247a91..1aa9fee 100644 --- a/include/xtensor-python/pyarray.hpp +++ b/include/xtensor-python/pyarray.hpp @@ -75,21 +75,183 @@ namespace pybind11 namespace xt { + /************************** + * pybackstrides_iterator * + **************************/ + + template + class pybackstrides_iterator + { + public: + + using self_type = pybackstrides_iterator; + + using value_type = typename B::value_type; + using pointer = const value_type*; + using reference = value_type; + using difference_type = std::ptrdiff_t; + using iterator_category = std::random_access_iterator_tag; + + inline pybackstrides_iterator(const B* b, std::size_t offset) + : p_b(b), m_offset(offset) + { + } + + inline reference operator*() const + { + return p_b->operator[](m_offset); + } + + inline pointer operator->() const + { + // Returning the address of a temporary + value_type res = p_b->operator[](m_offset); + return &res; + } + + inline reference operator[](difference_type n) const + { + return p_b->operator[](m_offset + n); + } + + inline self_type& operator++() + { + ++m_offset; + return *this; + } + + inline self_type& operator--() + { + --m_offset; + return *this; + } + + inline self_type operator++(int) + { + self_type tmp(*this); + ++m_offset; + return tmp; + } + + inline self_type operator--(int) + { + self_type tmp(*this); + --m_offset; + return tmp; + } + + inline self_type& operator+=(difference_type n) + { + m_offset += n; + return *this; + } + + inline self_type& operator-=(difference_type n) + { + m_offset -= n; + return *this; + } + + inline self_type operator+(difference_type n) const + { + return self_type(p_b, m_offset + n); + } + + inline self_type operator-(difference_type n) const + { + return self_type(p_b, m_offset - n); + } + + inline self_type operator-(const self_type& rhs) const + { + self_type tmp(*this); + tmp -= (m_offset - rhs.m_offset); + return tmp; + } + + inline std::size_t offset() const + { + return m_offset; + } + + private: + + const B* p_b; + std::size_t m_offset; + }; + + template + inline bool operator==(const pybackstrides_iterator& lhs, + const pybackstrides_iterator& rhs) + { + return lhs.offset() == rhs.offset(); + } + + template + inline bool operator!=(const pybackstrides_iterator& lhs, + const pybackstrides_iterator& rhs) + { + return !(lhs == rhs); + } + + template + inline bool operator<(const pybackstrides_iterator& lhs, + const pybackstrides_iterator& rhs) + { + return lhs.offset() < rhs.offset(); + } + + template + inline bool operator<=(const pybackstrides_iterator& lhs, + const pybackstrides_iterator& rhs) + { + return (lhs < rhs) || (lhs == rhs); + } + + template + inline bool operator>(const pybackstrides_iterator& lhs, + const pybackstrides_iterator& rhs) + { + return !(lhs <= rhs); + } + + template + inline bool operator>=(const pybackstrides_iterator& lhs, + const pybackstrides_iterator& rhs) + { + return !(lhs < rhs); + } + template class pyarray_backstrides { public: + using self_type = pyarray_backstrides; using array_type = A; using value_type = typename array_type::size_type; + using const_reference = value_type; + using const_pointer = const value_type*; using size_type = typename array_type::size_type; + using difference_type = typename array_type::difference_type; + + using const_iterator = pybackstrides_iterator; pyarray_backstrides() = default; pyarray_backstrides(const array_type& a); + bool empty() const; + size_type size() const; + value_type operator[](size_type i) const; - size_type size() const; + const_reference front() const; + const_reference back() const; + + const_iterator begin() const; + const_iterator end() const; + const_iterator cbegin() const; + const_iterator cend() const; private: @@ -213,6 +375,12 @@ namespace xt { } + template + inline bool pyarray_backstrides::empty() const + { + return p_a->dimension() == 0; + } + template inline auto pyarray_backstrides::size() const -> size_type { @@ -227,6 +395,47 @@ namespace xt return res; } + template + inline auto pyarray_backstrides::front() const -> const_reference + { + value_type sh = p_a->shape()[0]; + value_type res = sh == 1 ? 0 : (sh - 1) * p_a->strides()[0]; + return res; + } + + template + inline auto pyarray_backstrides::back() const -> const_reference + { + auto index = p_a->size() - 1; + value_type sh = p_a->shape()[index]; + value_type res = sh == 1 ? 0 : (sh - 1) * p_a->strides()[index]; + return res; + } + + template + inline auto pyarray_backstrides::begin() const -> const_iterator + { + return cbegin(); + } + + template + inline auto pyarray_backstrides::end() const -> const_iterator + { + return cend(); + } + + template + inline auto pyarray_backstrides::cbegin() const -> const_iterator + { + const_iterator(this, 0); + } + + template + inline auto pyarray_backstrides::cend() const -> const_iterator + { + const_iterator(this, size()); + } + /************************** * pyarray implementation * **************************/ diff --git a/include/xtensor-python/pystrides_adaptor.hpp b/include/xtensor-python/pystrides_adaptor.hpp index 3492676..aa9c9ed 100644 --- a/include/xtensor-python/pystrides_adaptor.hpp +++ b/include/xtensor-python/pystrides_adaptor.hpp @@ -18,6 +18,10 @@ namespace xt template class pystrides_iterator; + /********************************* + * pystrides_adaptor declaration * + *********************************/ + template class pystrides_adaptor { @@ -53,14 +57,13 @@ namespace xt size_type m_size; }; - /************************************* - * pystrides_iterator implementation * - *************************************/ + /********************************** + * pystrides_iterator declaration * + **********************************/ template class pystrides_iterator { - public: using self_type = pystrides_iterator; @@ -76,16 +79,29 @@ namespace xt { } - inline reference operator*() const { return *p_current / N; } - inline pointer operator->() const { return p_current; } + inline reference operator*() const + { + return *p_current / N; + } - inline reference operator[](difference_type n) const { return *(p_current + n) / N; } + inline pointer operator->() const + { + // Returning the address of a temporary + value_type res = *p_current / N; + return &res; + } + + inline reference operator[](difference_type n) const + { + return *(p_current + n) / N; + } inline self_type& operator++() { ++p_current; return *this; } + inline self_type& operator--() { --p_current; @@ -110,14 +126,23 @@ namespace xt p_current += n; return *this; } + inline self_type& operator-=(difference_type n) { p_current -= n; return *this; } - inline self_type operator+(difference_type n) const { return self_type(p_current + n); } - inline self_type operator-(difference_type n) const { return self_type(p_current - n); } + inline self_type operator+(difference_type n) const + { + return self_type(p_current + n); + } + + inline self_type operator-(difference_type n) const + { + return self_type(p_current - n); + } + inline self_type operator-(const self_type& rhs) const { self_type tmp(*this); @@ -217,25 +242,25 @@ namespace xt template inline auto pystrides_adaptor::begin() const -> const_iterator { - return const_iterator(p_data); + return cbegin(); } template inline auto pystrides_adaptor::end() const -> const_iterator { - return const_iterator(p_data + m_size); + return cend(); } template inline auto pystrides_adaptor::cbegin() const -> const_iterator { - return begin(); + return const_iterator(p_data); } template inline auto pystrides_adaptor::cend() const -> const_iterator { - return end(); + return const_iterator(p_data + m_size); } }