]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/python/src/numpy/ndarray.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / python / src / numpy / ndarray.cpp
CommitLineData
7c673cae
FG
1// Copyright Jim Bosch 2010-2012.
2// Copyright Stefan Seefeld 2016.
3// Distributed under the Boost Software License, Version 1.0.
4// (See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6
7#define BOOST_PYTHON_NUMPY_INTERNAL
8#include <boost/python/numpy/internal.hpp>
9#include <boost/scoped_array.hpp>
10
11namespace boost { namespace python {
12namespace converter
13{
14NUMPY_OBJECT_MANAGER_TRAITS_IMPL(PyArray_Type, numpy::ndarray)
15} // namespace boost::python::converter
16
17namespace numpy
18{
19namespace detail
20{
21
22ndarray::bitflag numpy_to_bitflag(int const f)
23{
24 ndarray::bitflag r = ndarray::NONE;
b32b8144
FG
25 if (f & NPY_ARRAY_C_CONTIGUOUS) r = (r | ndarray::C_CONTIGUOUS);
26 if (f & NPY_ARRAY_F_CONTIGUOUS) r = (r | ndarray::F_CONTIGUOUS);
27 if (f & NPY_ARRAY_ALIGNED) r = (r | ndarray::ALIGNED);
28 if (f & NPY_ARRAY_WRITEABLE) r = (r | ndarray::WRITEABLE);
7c673cae
FG
29 return r;
30}
31
32int bitflag_to_numpy(ndarray::bitflag f)
33{
34 int r = 0;
b32b8144
FG
35 if (f & ndarray::C_CONTIGUOUS) r |= NPY_ARRAY_C_CONTIGUOUS;
36 if (f & ndarray::F_CONTIGUOUS) r |= NPY_ARRAY_F_CONTIGUOUS;
37 if (f & ndarray::ALIGNED) r |= NPY_ARRAY_ALIGNED;
38 if (f & ndarray::WRITEABLE) r |= NPY_ARRAY_WRITEABLE;
7c673cae
FG
39 return r;
40}
41
42bool is_c_contiguous(std::vector<Py_intptr_t> const & shape,
43 std::vector<Py_intptr_t> const & strides,
44 int itemsize)
45{
46 std::vector<Py_intptr_t>::const_reverse_iterator j = strides.rbegin();
47 int total = itemsize;
48 for (std::vector<Py_intptr_t>::const_reverse_iterator i = shape.rbegin(); i != shape.rend(); ++i, ++j)
49 {
50 if (total != *j) return false;
51 total *= (*i);
52 }
53 return true;
54}
55
56bool is_f_contiguous(std::vector<Py_intptr_t> const & shape,
57 std::vector<Py_intptr_t> const & strides,
58 int itemsize)
59{
60 std::vector<Py_intptr_t>::const_iterator j = strides.begin();
61 int total = itemsize;
62 for (std::vector<Py_intptr_t>::const_iterator i = shape.begin(); i != shape.end(); ++i, ++j)
63 {
64 if (total != *j) return false;
65 total *= (*i);
66 }
67 return true;
68}
69
70bool is_aligned(std::vector<Py_intptr_t> const & strides,
71 int itemsize)
72{
73 for (std::vector<Py_intptr_t>::const_iterator i = strides.begin(); i != strides.end(); ++i)
74 {
75 if (*i % itemsize) return false;
76 }
77 return true;
78}
79
80inline PyArray_Descr * incref_dtype(dtype const & dt)
81{
82 Py_INCREF(dt.ptr());
83 return reinterpret_cast<PyArray_Descr*>(dt.ptr());
84}
85
86ndarray from_data_impl(void * data,
87 dtype const & dt,
88 python::object const & shape,
89 python::object const & strides,
90 python::object const & owner,
91 bool writeable)
92{
93 std::vector<Py_intptr_t> shape_(len(shape));
94 std::vector<Py_intptr_t> strides_(len(strides));
95 if (shape_.size() != strides_.size())
96 {
97 PyErr_SetString(PyExc_ValueError, "Length of shape and strides arrays do not match.");
98 python::throw_error_already_set();
99 }
100 for (std::size_t i = 0; i < shape_.size(); ++i)
101 {
102 shape_[i] = python::extract<Py_intptr_t>(shape[i]);
103 strides_[i] = python::extract<Py_intptr_t>(strides[i]);
104 }
105 return from_data_impl(data, dt, shape_, strides_, owner, writeable);
106}
107
108ndarray from_data_impl(void * data,
109 dtype const & dt,
110 std::vector<Py_intptr_t> const & shape,
111 std::vector<Py_intptr_t> const & strides,
112 python::object const & owner,
113 bool writeable)
114{
115 if (shape.size() != strides.size())
116 {
117 PyErr_SetString(PyExc_ValueError, "Length of shape and strides arrays do not match.");
118 python::throw_error_already_set();
119 }
120 int itemsize = dt.get_itemsize();
121 int flags = 0;
b32b8144
FG
122 if (writeable) flags |= NPY_ARRAY_WRITEABLE;
123 if (is_c_contiguous(shape, strides, itemsize)) flags |= NPY_ARRAY_C_CONTIGUOUS;
124 if (is_f_contiguous(shape, strides, itemsize)) flags |= NPY_ARRAY_F_CONTIGUOUS;
125 if (is_aligned(strides, itemsize)) flags |= NPY_ARRAY_ALIGNED;
7c673cae
FG
126 ndarray r(python::detail::new_reference
127 (PyArray_NewFromDescr(&PyArray_Type,
128 incref_dtype(dt),
129 shape.size(),
130 const_cast<Py_intptr_t*>(&shape.front()),
131 const_cast<Py_intptr_t*>(&strides.front()),
132 data,
133 flags,
134 NULL)));
135 r.set_base(owner);
136 return r;
137}
138
139} // namespace detail
140
b32b8144
FG
141namespace {
142 int normalize_index(int n,int nlim) // wraps [-nlim:nlim) into [0:nlim), throw IndexError otherwise
143 {
144 if (n<0)
145 n += nlim; // negative indices work backwards from end
146 if (n < 0 || n >= nlim)
147 {
148 PyErr_SetObject(PyExc_IndexError, Py_None);
149 throw_error_already_set();
150 }
151 return n;
152 }
153}
154
155Py_intptr_t ndarray::shape(int n) const
156{
157 return get_shape()[normalize_index(n,get_nd())];
158}
159
160Py_intptr_t ndarray::strides(int n) const
161{
162 return get_strides()[normalize_index(n,get_nd())];
163}
164
7c673cae
FG
165ndarray ndarray::view(dtype const & dt) const
166{
167 return ndarray(python::detail::new_reference
168 (PyObject_CallMethod(this->ptr(), const_cast<char*>("view"), const_cast<char*>("O"), dt.ptr())));
169}
170
171ndarray ndarray::astype(dtype const & dt) const
172{
173 return ndarray(python::detail::new_reference
174 (PyObject_CallMethod(this->ptr(), const_cast<char*>("astype"), const_cast<char*>("O"), dt.ptr())));
175}
176
177ndarray ndarray::copy() const
178{
179 return ndarray(python::detail::new_reference
180 (PyObject_CallMethod(this->ptr(), const_cast<char*>("copy"), const_cast<char*>(""))));
181}
182
183dtype ndarray::get_dtype() const
184{
185 return dtype(python::detail::borrowed_reference(get_struct()->descr));
186}
187
188python::object ndarray::get_base() const
189{
190 if (get_struct()->base == NULL) return object();
191 return python::object(python::detail::borrowed_reference(get_struct()->base));
192}
193
194void ndarray::set_base(object const & base)
195{
196 Py_XDECREF(get_struct()->base);
b32b8144 197 if (base.ptr())
7c673cae
FG
198 {
199 Py_INCREF(base.ptr());
200 get_struct()->base = base.ptr();
201 }
202 else
203 {
204 get_struct()->base = NULL;
205 }
206}
207
208ndarray::bitflag ndarray::get_flags() const
209{
210 return numpy::detail::numpy_to_bitflag(get_struct()->flags);
211}
212
213ndarray ndarray::transpose() const
214{
215 return ndarray(python::detail::new_reference
216 (PyArray_Transpose(reinterpret_cast<PyArrayObject*>(this->ptr()), NULL)));
217}
218
219ndarray ndarray::squeeze() const
220{
221 return ndarray(python::detail::new_reference
222 (PyArray_Squeeze(reinterpret_cast<PyArrayObject*>(this->ptr()))));
223}
224
225ndarray ndarray::reshape(python::tuple const & shape) const
226{
227 return ndarray(python::detail::new_reference
228 (PyArray_Reshape(reinterpret_cast<PyArrayObject*>(this->ptr()), shape.ptr())));
229}
230
231python::object ndarray::scalarize() const
232{
233 Py_INCREF(ptr());
234 return python::object(python::detail::new_reference(PyArray_Return(reinterpret_cast<PyArrayObject*>(ptr()))));
235}
236
237ndarray zeros(python::tuple const & shape, dtype const & dt)
238{
239 int nd = len(shape);
240 boost::scoped_array<Py_intptr_t> dims(new Py_intptr_t[nd]);
241 for (int n=0; n<nd; ++n) dims[n] = python::extract<Py_intptr_t>(shape[n]);
242 return ndarray(python::detail::new_reference
243 (PyArray_Zeros(nd, dims.get(), detail::incref_dtype(dt), 0)));
244}
245
246ndarray zeros(int nd, Py_intptr_t const * shape, dtype const & dt)
247{
248 return ndarray(python::detail::new_reference
249 (PyArray_Zeros(nd, const_cast<Py_intptr_t*>(shape), detail::incref_dtype(dt), 0)));
250}
251
252ndarray empty(python::tuple const & shape, dtype const & dt)
253{
254 int nd = len(shape);
255 boost::scoped_array<Py_intptr_t> dims(new Py_intptr_t[nd]);
256 for (int n=0; n<nd; ++n) dims[n] = python::extract<Py_intptr_t>(shape[n]);
257 return ndarray(python::detail::new_reference
258 (PyArray_Empty(nd, dims.get(), detail::incref_dtype(dt), 0)));
259}
260
261ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt)
262{
263 return ndarray(python::detail::new_reference
264 (PyArray_Empty(nd, const_cast<Py_intptr_t*>(shape), detail::incref_dtype(dt), 0)));
265}
266
267ndarray array(python::object const & obj)
268{
269 return ndarray(python::detail::new_reference
b32b8144 270 (PyArray_FromAny(obj.ptr(), NULL, 0, 0, NPY_ARRAY_ENSUREARRAY, NULL)));
7c673cae
FG
271}
272
273ndarray array(python::object const & obj, dtype const & dt)
274{
275 return ndarray(python::detail::new_reference
b32b8144 276 (PyArray_FromAny(obj.ptr(), detail::incref_dtype(dt), 0, 0, NPY_ARRAY_ENSUREARRAY, NULL)));
7c673cae
FG
277}
278
279ndarray from_object(python::object const & obj, dtype const & dt, int nd_min, int nd_max, ndarray::bitflag flags)
280{
281 int requirements = detail::bitflag_to_numpy(flags);
282 return ndarray(python::detail::new_reference
283 (PyArray_FromAny(obj.ptr(),
284 detail::incref_dtype(dt),
285 nd_min, nd_max,
286 requirements,
287 NULL)));
288}
289
290ndarray from_object(python::object const & obj, int nd_min, int nd_max, ndarray::bitflag flags)
291{
292 int requirements = detail::bitflag_to_numpy(flags);
293 return ndarray(python::detail::new_reference
294 (PyArray_FromAny(obj.ptr(),
295 NULL,
296 nd_min, nd_max,
297 requirements,
298 NULL)));
299}
300
301}}} // namespace boost::python::numpy