/*************************************************************************** * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * * 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 PY_ARRAY_BACKSTRIDES_HPP #define PY_ARRAY_BACKSTRIDES_HPP #include #include 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; pybackstrides_iterator(const B* b, std::size_t offset); reference operator*() const; pointer operator->() const; reference operator[](difference_type n) const; self_type& operator++(); self_type& operator--(); self_type operator++(int); self_type operator--(int); self_type& operator+=(difference_type n); self_type& operator-=(difference_type n); self_type operator+(difference_type n) const; self_type operator-(difference_type n) const; self_type operator-(const self_type& rhs) const; std::size_t offset() const; private: const B* p_b; std::size_t m_offset; }; template inline bool operator==(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); template inline bool operator!=(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); template inline bool operator<(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); template inline bool operator<=(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); template inline bool operator>(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); template inline bool operator>=(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); /*********************** * pyarray_backstrides * ***********************/ 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 reference = const_reference; using const_pointer = const value_type*; using pointer = const_pointer; using size_type = typename array_type::size_type; using difference_type = typename array_type::difference_type; using const_iterator = pybackstrides_iterator; using iterator = const_iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; pyarray_backstrides() = default; pyarray_backstrides(const array_type& a); bool empty() const; size_type size() const; value_type operator[](size_type i) 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; const_reverse_iterator rbegin() const; const_reverse_iterator rend() const; const_reverse_iterator crbegin() const; const_reverse_iterator crend() const; private: const array_type* p_a; }; /***************************************** * pybackstrides_iterator implementation * *****************************************/ template inline pybackstrides_iterator::pybackstrides_iterator(const B* b, std::size_t offset) : p_b(b), m_offset(offset) { } template inline auto pybackstrides_iterator::operator*() const -> reference { return p_b->operator[](m_offset); } template inline auto pybackstrides_iterator::operator->() const -> pointer { // Returning the address of a temporary value_type res = p_b->operator[](m_offset); return &res; } template inline auto pybackstrides_iterator::operator[](difference_type n) const -> reference { return p_b->operator[](m_offset + n); } template inline auto pybackstrides_iterator::operator++() -> self_type& { ++m_offset; return *this; } template inline auto pybackstrides_iterator::operator--() -> self_type& { --m_offset; return *this; } template inline auto pybackstrides_iterator::operator++(int )-> self_type { self_type tmp(*this); ++m_offset; return tmp; } template inline auto pybackstrides_iterator::operator--(int) -> self_type { self_type tmp(*this); --m_offset; return tmp; } template inline auto pybackstrides_iterator::operator+=(difference_type n) -> self_type& { m_offset += n; return *this; } template inline auto pybackstrides_iterator::operator-=(difference_type n) -> self_type& { m_offset -= n; return *this; } template inline auto pybackstrides_iterator::operator+(difference_type n) const -> self_type { return self_type(p_b, m_offset + n); } template inline auto pybackstrides_iterator::operator-(difference_type n) const -> self_type { return self_type(p_b, m_offset - n); } template inline auto pybackstrides_iterator::operator-(const self_type& rhs) const -> self_type { self_type tmp(*this); tmp -= (m_offset - rhs.m_offset); return tmp; } template inline std::size_t pybackstrides_iterator::offset() const { return 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); } /************************************** * pyarray_backstrides implementation * **************************************/ template inline pyarray_backstrides::pyarray_backstrides(const array_type& a) : p_a(&a) { } template inline bool pyarray_backstrides::empty() const { return p_a->dimension() == 0; } template inline auto pyarray_backstrides::size() const -> size_type { return p_a->dimension(); } template inline auto pyarray_backstrides::operator[](size_type i) const -> value_type { value_type sh = p_a->shape()[i]; value_type res = sh == 1 ? 0 : (sh - 1) * p_a->strides()[i]; 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 { return const_iterator(this, 0); } template inline auto pyarray_backstrides::cend() const -> const_iterator { return const_iterator(this, size()); } template inline auto pyarray_backstrides::rbegin() const -> const_reverse_iterator { return crbegin(); } template inline auto pyarray_backstrides::rend() const -> const_reverse_iterator { return crend(); } template inline auto pyarray_backstrides::crbegin() const -> const_reverse_iterator { return const_reverse_iterator(end()); } template inline auto pyarray_backstrides::crend() const -> const_reverse_iterator { return const_reverse_iterator(begin()); } } #endif