Skip to content

Commit c8bb9d6

Browse files
committed
copy semantic fixed
1 parent adf3ab5 commit c8bb9d6

File tree

5 files changed

+100
-10
lines changed

5 files changed

+100
-10
lines changed

include/xtensor-python/pyarray.hpp

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,6 @@ namespace xt
134134
using inner_backstrides_type = typename base_type::inner_backstrides_type;
135135

136136
pyarray();
137-
pyarray(const self_type&) = default;
138-
pyarray(self_type&&) = default;
139137
pyarray(const value_type& t);
140138
pyarray(nested_initializer_list_t<T, 1> t);
141139
pyarray(nested_initializer_list_t<T, 2> t);
@@ -152,12 +150,15 @@ namespace xt
152150
explicit pyarray(const shape_type& shape, const strides_type& strides, const_reference value);
153151
explicit pyarray(const shape_type& shape, const strides_type& strides);
154152

155-
template <class E>
156-
pyarray(const xexpression<E>& e);
153+
pyarray(const self_type& rhs);
154+
self_type& operator=(const self_type& rhs);
157155

158-
self_type& operator=(const self_type& e) = default;
156+
pyarray(self_type&&) = default;
159157
self_type& operator=(self_type&& e) = default;
160158

159+
template <class E>
160+
pyarray(const xexpression<E>& e);
161+
161162
template <class E>
162163
self_type& operator=(const xexpression<E>& e);
163164

@@ -221,6 +222,7 @@ namespace xt
221222
//@{
222223
template <class T>
223224
inline pyarray<T>::pyarray()
225+
: base_type()
224226
{
225227
// TODO: avoid allocation
226228
shape_type shape = make_sequence<shape_type>(0, size_type(1));
@@ -234,41 +236,47 @@ namespace xt
234236
*/
235237
template <class T>
236238
inline pyarray<T>::pyarray(const value_type& t)
239+
: base_type()
237240
{
238241
base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
239242
nested_copy(m_data.begin(), t);
240243
}
241244

242245
template <class T>
243246
inline pyarray<T>::pyarray(nested_initializer_list_t<T, 1> t)
247+
: base_type()
244248
{
245249
base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
246250
nested_copy(m_data.begin(), t);
247251
}
248252

249253
template <class T>
250254
inline pyarray<T>::pyarray(nested_initializer_list_t<T, 2> t)
255+
: base_type()
251256
{
252257
base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
253258
nested_copy(m_data.begin(), t);
254259
}
255260

256261
template <class T>
257262
inline pyarray<T>::pyarray(nested_initializer_list_t<T, 3> t)
263+
: base_type()
258264
{
259265
base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
260266
nested_copy(m_data.begin(), t);
261267
}
262268

263269
template <class T>
264270
inline pyarray<T>::pyarray(nested_initializer_list_t<T, 4> t)
271+
: base_type()
265272
{
266273
base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
267274
nested_copy(m_data.begin(), t);
268275
}
269276

270277
template <class T>
271278
inline pyarray<T>::pyarray(nested_initializer_list_t<T, 5> t)
279+
: base_type()
272280
{
273281
base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
274282
nested_copy(m_data.begin(), t);
@@ -303,6 +311,7 @@ namespace xt
303311
*/
304312
template <class T>
305313
inline pyarray<T>::pyarray(const shape_type& shape, layout l)
314+
: base_type()
306315
{
307316
strides_type strides(shape.size());
308317
compute_strides(shape, l, strides);
@@ -318,6 +327,7 @@ namespace xt
318327
*/
319328
template <class T>
320329
inline pyarray<T>::pyarray(const shape_type& shape, const_reference value, layout l)
330+
: base_type()
321331
{
322332
strides_type strides(shape.size());
323333
compute_strides(shape, l, strides);
@@ -334,6 +344,7 @@ namespace xt
334344
*/
335345
template <class T>
336346
inline pyarray<T>::pyarray(const shape_type& shape, const strides_type& strides, const_reference value)
347+
: base_type()
337348
{
338349
init_array(shape, strides);
339350
std::fill(m_data.begin(), m_data.end(), value);
@@ -346,11 +357,50 @@ namespace xt
346357
*/
347358
template <class T>
348359
inline pyarray<T>::pyarray(const shape_type& shape, const strides_type& strides)
360+
: base_type()
349361
{
350362
init_array(shape, strides);
351363
}
352364
//@}
353365

366+
/**
367+
* @name Copy semantic
368+
*/
369+
//@{
370+
/**
371+
* The copy constructor.
372+
*/
373+
template <class T>
374+
inline pyarray<T>::pyarray(const self_type& rhs)
375+
: base_type()
376+
{
377+
auto tmp = pybind11::reinterpret_steal<pybind11::object>(
378+
PyArray_NewLikeArray(rhs.python_array(), NPY_KEEPORDER, nullptr, 1)
379+
);
380+
381+
if (!tmp)
382+
{
383+
throw std::runtime_error("NumPy: unable to create ndarray");
384+
}
385+
386+
this->m_ptr = tmp.release().ptr();
387+
init_from_python();
388+
std::copy(rhs.data().begin(), rhs.data().end(), this->data().begin());
389+
}
390+
391+
/**
392+
* The assignment operator.
393+
*/
394+
template <class T>
395+
inline auto pyarray<T>::operator=(const self_type& rhs) -> self_type&
396+
{
397+
self_type tmp(rhs);
398+
*this = std::move(tmp);
399+
return *this;
400+
}
401+
402+
//@}
403+
354404
/**
355405
* @name Extended copy semantic
356406
*/
@@ -361,6 +411,7 @@ namespace xt
361411
template <class T>
362412
template <class E>
363413
inline pyarray<T>::pyarray(const xexpression<E>& e)
414+
: base_type()
364415
{
365416
semantic_base::assign(e);
366417
}

include/xtensor-python/pycontainer.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ namespace xt
108108
static bool check_(pybind11::handle h);
109109
static PyObject* raw_array_t(PyObject* ptr);
110110

111-
PyArrayObject* python_array();
111+
PyArrayObject* python_array() const;
112112
};
113113

114114
namespace detail
@@ -199,7 +199,7 @@ namespace xt
199199
}
200200

201201
template <class D>
202-
inline PyArrayObject* pycontainer<D>::python_array()
202+
inline PyArrayObject* pycontainer<D>::python_array() const
203203
{
204204
return reinterpret_cast<PyArrayObject*>(this->m_ptr);
205205
}

include/xtensor-python/pytensor.hpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,6 @@ namespace xt
118118
using inner_backstrides_type = typename base_type::inner_backstrides_type;
119119

120120
pytensor();
121-
pytensor(const self_type&) = default;
122-
pytensor(self_type&&) = default;
123121
pytensor(nested_initializer_list_t<T, N> t);
124122
pytensor(pybind11::handle h, pybind11::object::borrowed_t);
125123
pytensor(pybind11::handle h, pybind11::object::stolen_t);
@@ -130,7 +128,10 @@ namespace xt
130128
explicit pytensor(const shape_type& shape, const strides_type& strides, const_reference value);
131129
explicit pytensor(const shape_type& shape, const strides_type& strides);
132130

133-
self_type& operator=(const self_type& e) = default;
131+
pytensor(const self_type& rhs) ;
132+
self_type& operator=(const self_type& rhs);
133+
134+
pytensor(self_type&&) = default;
134135
self_type& operator=(self_type&& e) = default;
135136

136137
template <class E>
@@ -181,6 +182,7 @@ namespace xt
181182
*/
182183
template <class T, std::size_t N>
183184
inline pytensor<T, N>::pytensor()
185+
: base_type()
184186
{
185187
m_shape = make_sequence<shape_type>(N, size_type(1));
186188
m_strides = make_sequence<strides_type>(N, size_type(0));
@@ -193,6 +195,7 @@ namespace xt
193195
*/
194196
template <class T, std::size_t N>
195197
inline pytensor<T, N>::pytensor(nested_initializer_list_t<T, N> t)
198+
: base_type()
196199
{
197200
base_type::reshape(xt::shape<shape_type>(t), layout::row_major);
198201
nested_copy(m_data.begin(), t);
@@ -278,6 +281,33 @@ namespace xt
278281
}
279282
//@}
280283

284+
/**
285+
* @name Copy semantic
286+
*/
287+
//@{
288+
/**
289+
* The copy constructor.
290+
*/
291+
template <class T, std::size_t N>
292+
inline pytensor<T, N>::pytensor(const self_type& rhs)
293+
: base_type()
294+
{
295+
init_tensor(rhs.shape(), rhs.strides());
296+
std::copy(rhs.data().begin(), rhs.data().end(), this->data().begin());
297+
}
298+
299+
/**
300+
* The assignment operator.
301+
*/
302+
template <class T, std::size_t N>
303+
inline auto pytensor<T, N>::operator=(const self_type& rhs) -> self_type&
304+
{
305+
self_type tmp(rhs);
306+
*this = std::move(tmp);
307+
return *this;
308+
}
309+
//@}
310+
281311
/**
282312
* @name Extended copy semantic
283313
*/
@@ -288,6 +318,7 @@ namespace xt
288318
template <class T, std::size_t N>
289319
template <class E>
290320
inline pytensor<T, N>::pytensor(const xexpression<E>& e)
321+
: base_type()
291322
{
292323
semantic_base::assign(e);
293324
}

test/test_pyarray.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ namespace xt
9797
pyarray<int> b(a);
9898
compare_shape(a, b);
9999
EXPECT_EQ(a.data(), b.data());
100+
a.data()[0] += 1;
101+
EXPECT_NE(a.data()[0], b.data()[0]);
100102
}
101103

102104
{
@@ -107,6 +109,8 @@ namespace xt
107109
c = a;
108110
compare_shape(a, c);
109111
EXPECT_EQ(a.data(), c.data());
112+
a.data()[0] += 1;
113+
EXPECT_NE(a.data()[0], c.data()[0]);
110114
}
111115
}
112116

test/test_pytensor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ namespace xt
9696
pytensor<int, 3> b(a);
9797
compare_shape(a, b);
9898
EXPECT_EQ(a.data(), b.data());
99+
a.data()[0] += 1;
100+
EXPECT_NE(a.data()[0], b.data()[0]);
99101
}
100102

101103
{
@@ -106,6 +108,8 @@ namespace xt
106108
c = a;
107109
compare_shape(a, c);
108110
EXPECT_EQ(a.data(), c.data());
111+
a.data()[0] += 1;
112+
EXPECT_NE(a.data()[0], c.data()[0]);
109113
}
110114
}
111115

0 commit comments

Comments
 (0)