Skip to content

Commit 1198e84

Browse files
committed
Enabling iterator pairs on pyarray backstrides
1 parent 75e68b0 commit 1198e84

File tree

2 files changed

+248
-14
lines changed

2 files changed

+248
-14
lines changed

include/xtensor-python/pyarray.hpp

Lines changed: 210 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,183 @@ namespace pybind11
7575
namespace xt
7676
{
7777

78+
/**************************
79+
* pybackstrides_iterator *
80+
**************************/
81+
82+
template <class B>
83+
class pybackstrides_iterator
84+
{
85+
public:
86+
87+
using self_type = pybackstrides_iterator<B>;
88+
89+
using value_type = typename B::value_type;
90+
using pointer = const value_type*;
91+
using reference = value_type;
92+
using difference_type = std::ptrdiff_t;
93+
using iterator_category = std::random_access_iterator_tag;
94+
95+
inline pybackstrides_iterator(const B* b, std::size_t offset)
96+
: p_b(b), m_offset(offset)
97+
{
98+
}
99+
100+
inline reference operator*() const
101+
{
102+
return p_b->operator[](m_offset);
103+
}
104+
105+
inline pointer operator->() const
106+
{
107+
// Returning the address of a temporary
108+
value_type res = p_b->operator[](m_offset);
109+
return &res;
110+
}
111+
112+
inline reference operator[](difference_type n) const
113+
{
114+
return p_b->operator[](m_offset + n);
115+
}
116+
117+
inline self_type& operator++()
118+
{
119+
++m_offset;
120+
return *this;
121+
}
122+
123+
inline self_type& operator--()
124+
{
125+
--m_offset;
126+
return *this;
127+
}
128+
129+
inline self_type operator++(int)
130+
{
131+
self_type tmp(*this);
132+
++m_offset;
133+
return tmp;
134+
}
135+
136+
inline self_type operator--(int)
137+
{
138+
self_type tmp(*this);
139+
--m_offset;
140+
return tmp;
141+
}
142+
143+
inline self_type& operator+=(difference_type n)
144+
{
145+
m_offset += n;
146+
return *this;
147+
}
148+
149+
inline self_type& operator-=(difference_type n)
150+
{
151+
m_offset -= n;
152+
return *this;
153+
}
154+
155+
inline self_type operator+(difference_type n) const
156+
{
157+
return self_type(p_b, m_offset + n);
158+
}
159+
160+
inline self_type operator-(difference_type n) const
161+
{
162+
return self_type(p_b, m_offset - n);
163+
}
164+
165+
inline self_type operator-(const self_type& rhs) const
166+
{
167+
self_type tmp(*this);
168+
tmp -= (m_offset - rhs.m_offset);
169+
return tmp;
170+
}
171+
172+
inline std::size_t offset() const
173+
{
174+
return m_offset;
175+
}
176+
177+
private:
178+
179+
const B* p_b;
180+
std::size_t m_offset;
181+
};
182+
183+
template <class B>
184+
inline bool operator==(const pybackstrides_iterator<B>& lhs,
185+
const pybackstrides_iterator<B>& rhs)
186+
{
187+
return lhs.offset() == rhs.offset();
188+
}
189+
190+
template <class B>
191+
inline bool operator!=(const pybackstrides_iterator<B>& lhs,
192+
const pybackstrides_iterator<B>& rhs)
193+
{
194+
return !(lhs == rhs);
195+
}
196+
197+
template <class B>
198+
inline bool operator<(const pybackstrides_iterator<B>& lhs,
199+
const pybackstrides_iterator<B>& rhs)
200+
{
201+
return lhs.offset() < rhs.offset();
202+
}
203+
204+
template <class B>
205+
inline bool operator<=(const pybackstrides_iterator<B>& lhs,
206+
const pybackstrides_iterator<B>& rhs)
207+
{
208+
return (lhs < rhs) || (lhs == rhs);
209+
}
210+
211+
template <class B>
212+
inline bool operator>(const pybackstrides_iterator<B>& lhs,
213+
const pybackstrides_iterator<B>& rhs)
214+
{
215+
return !(lhs <= rhs);
216+
}
217+
218+
template <class B>
219+
inline bool operator>=(const pybackstrides_iterator<B>& lhs,
220+
const pybackstrides_iterator<B>& rhs)
221+
{
222+
return !(lhs < rhs);
223+
}
224+
78225
template <class A>
79226
class pyarray_backstrides
80227
{
81228
public:
82229

230+
using self_type = pyarray_backstrides<A>;
83231
using array_type = A;
84232
using value_type = typename array_type::size_type;
233+
using const_reference = value_type;
234+
using const_pointer = const value_type*;
85235
using size_type = typename array_type::size_type;
236+
using difference_type = typename array_type::difference_type;
237+
238+
using const_iterator = pybackstrides_iterator<self_type>;
86239

87240
pyarray_backstrides() = default;
88241
pyarray_backstrides(const array_type& a);
89242

243+
bool empty() const;
244+
size_type size() const;
245+
90246
value_type operator[](size_type i) const;
91247

92-
size_type size() const;
248+
const_reference front() const;
249+
const_reference back() const;
250+
251+
const_iterator begin() const;
252+
const_iterator end() const;
253+
const_iterator cbegin() const;
254+
const_iterator cend() const;
93255

94256
private:
95257

@@ -213,6 +375,12 @@ namespace xt
213375
{
214376
}
215377

378+
template <class A>
379+
inline bool pyarray_backstrides<A>::empty() const
380+
{
381+
return p_a->dimension() == 0;
382+
}
383+
216384
template <class A>
217385
inline auto pyarray_backstrides<A>::size() const -> size_type
218386
{
@@ -227,6 +395,47 @@ namespace xt
227395
return res;
228396
}
229397

398+
template <class A>
399+
inline auto pyarray_backstrides<A>::front() const -> const_reference
400+
{
401+
value_type sh = p_a->shape()[0];
402+
value_type res = sh == 1 ? 0 : (sh - 1) * p_a->strides()[0];
403+
return res;
404+
}
405+
406+
template <class A>
407+
inline auto pyarray_backstrides<A>::back() const -> const_reference
408+
{
409+
auto index = p_a->size() - 1;
410+
value_type sh = p_a->shape()[index];
411+
value_type res = sh == 1 ? 0 : (sh - 1) * p_a->strides()[index];
412+
return res;
413+
}
414+
415+
template <class A>
416+
inline auto pyarray_backstrides<A>::begin() const -> const_iterator
417+
{
418+
return cbegin();
419+
}
420+
421+
template <class A>
422+
inline auto pyarray_backstrides<A>::end() const -> const_iterator
423+
{
424+
return cend();
425+
}
426+
427+
template <class A>
428+
inline auto pyarray_backstrides<A>::cbegin() const -> const_iterator
429+
{
430+
const_iterator(this, 0);
431+
}
432+
433+
template <class A>
434+
inline auto pyarray_backstrides<A>::cend() const -> const_iterator
435+
{
436+
const_iterator(this, size());
437+
}
438+
230439
/**************************
231440
* pyarray implementation *
232441
**************************/

include/xtensor-python/pystrides_adaptor.hpp

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ namespace xt
1818
template <std::size_t N>
1919
class pystrides_iterator;
2020

21+
/*********************************
22+
* pystrides_adaptor declaration *
23+
*********************************/
24+
2125
template <std::size_t N>
2226
class pystrides_adaptor
2327
{
@@ -53,14 +57,13 @@ namespace xt
5357
size_type m_size;
5458
};
5559

56-
/*************************************
57-
* pystrides_iterator implementation *
58-
*************************************/
60+
/**********************************
61+
* pystrides_iterator declaration *
62+
**********************************/
5963

6064
template <std::size_t N>
6165
class pystrides_iterator
6266
{
63-
6467
public:
6568

6669
using self_type = pystrides_iterator<N>;
@@ -76,16 +79,29 @@ namespace xt
7679
{
7780
}
7881

79-
inline reference operator*() const { return *p_current / N; }
80-
inline pointer operator->() const { return p_current; }
82+
inline reference operator*() const
83+
{
84+
return *p_current / N;
85+
}
8186

82-
inline reference operator[](difference_type n) const { return *(p_current + n) / N; }
87+
inline pointer operator->() const
88+
{
89+
// Returning the address of a temporary
90+
value_type res = *p_current / N;
91+
return &res;
92+
}
93+
94+
inline reference operator[](difference_type n) const
95+
{
96+
return *(p_current + n) / N;
97+
}
8398

8499
inline self_type& operator++()
85100
{
86101
++p_current;
87102
return *this;
88103
}
104+
89105
inline self_type& operator--()
90106
{
91107
--p_current;
@@ -110,14 +126,23 @@ namespace xt
110126
p_current += n;
111127
return *this;
112128
}
129+
113130
inline self_type& operator-=(difference_type n)
114131
{
115132
p_current -= n;
116133
return *this;
117134
}
118135

119-
inline self_type operator+(difference_type n) const { return self_type(p_current + n); }
120-
inline self_type operator-(difference_type n) const { return self_type(p_current - n); }
136+
inline self_type operator+(difference_type n) const
137+
{
138+
return self_type(p_current + n);
139+
}
140+
141+
inline self_type operator-(difference_type n) const
142+
{
143+
return self_type(p_current - n);
144+
}
145+
121146
inline self_type operator-(const self_type& rhs) const
122147
{
123148
self_type tmp(*this);
@@ -217,25 +242,25 @@ namespace xt
217242
template <std::size_t N>
218243
inline auto pystrides_adaptor<N>::begin() const -> const_iterator
219244
{
220-
return const_iterator(p_data);
245+
return cbegin();
221246
}
222247

223248
template <std::size_t N>
224249
inline auto pystrides_adaptor<N>::end() const -> const_iterator
225250
{
226-
return const_iterator(p_data + m_size);
251+
return cend();
227252
}
228253

229254
template <std::size_t N>
230255
inline auto pystrides_adaptor<N>::cbegin() const -> const_iterator
231256
{
232-
return begin();
257+
return const_iterator(p_data);
233258
}
234259

235260
template <std::size_t N>
236261
inline auto pystrides_adaptor<N>::cend() const -> const_iterator
237262
{
238-
return end();
263+
return const_iterator(p_data + m_size);
239264
}
240265
}
241266

0 commit comments

Comments
 (0)