File: | numpy/core/src/multiarray/ctors.c |
Warning: | line 1681, column 13 Accessing a PyObject whose ownership has been released |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | #define PY_SSIZE_T_CLEAN | ||||||||
2 | #include <Python.h> | ||||||||
3 | #include "structmember.h" | ||||||||
4 | |||||||||
5 | /*#include <stdio.h>*/ | ||||||||
6 | #define NPY_NO_DEPRECATED_API0x0000000E NPY_API_VERSION0x0000000E | ||||||||
7 | #define _MULTIARRAYMODULE | ||||||||
8 | #include "numpy/arrayobject.h" | ||||||||
9 | #include "arrayobject.h" | ||||||||
10 | |||||||||
11 | #include "npy_config.h" | ||||||||
12 | |||||||||
13 | #include "npy_pycompat.h" | ||||||||
14 | #include "npy_import.h" | ||||||||
15 | |||||||||
16 | #include "common.h" | ||||||||
17 | #include "ctors.h" | ||||||||
18 | #include "descriptor.h" | ||||||||
19 | #include "iterators.h" | ||||||||
20 | #include "mapping.h" | ||||||||
21 | #include "lowlevel_strided_loops.h" | ||||||||
22 | #include "item_selection.h" | ||||||||
23 | #include "mem_overlap.h" | ||||||||
24 | #include "array_assign.h" | ||||||||
25 | #include "array_coercion.h" | ||||||||
26 | |||||||||
27 | |||||||||
28 | #define HAS_INTEGER 1 | ||||||||
29 | #define HAS_NEWAXIS 2 | ||||||||
30 | #define HAS_SLICE 4 | ||||||||
31 | #define HAS_ELLIPSIS 8 | ||||||||
32 | /* HAS_FANCY can be mixed with HAS_0D_BOOL, be careful when to use & or == */ | ||||||||
33 | #define HAS_FANCY 16 | ||||||||
34 | #define HAS_BOOL 32 | ||||||||
35 | /* NOTE: Only set if it is neither fancy nor purely integer index! */ | ||||||||
36 | #define HAS_SCALAR_ARRAY 64 | ||||||||
37 | /* | ||||||||
38 | * Indicate that this is a fancy index that comes from a 0d boolean. | ||||||||
39 | * This means that the index does not operate along a real axis. The | ||||||||
40 | * corresponding index type is just HAS_FANCY. | ||||||||
41 | */ | ||||||||
42 | #define HAS_0D_BOOL (HAS_FANCY | 128) | ||||||||
43 | |||||||||
44 | |||||||||
45 | static int | ||||||||
46 | _nonzero_indices(PyObject *myBool, PyArrayObject **arrays); | ||||||||
47 | |||||||||
48 | /****************************************************************************** | ||||||||
49 | *** IMPLEMENT MAPPING PROTOCOL *** | ||||||||
50 | *****************************************************************************/ | ||||||||
51 | |||||||||
52 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) Py_ssize_t | ||||||||
53 | array_length(PyArrayObject *self) | ||||||||
54 | { | ||||||||
55 | if (PyArray_NDIM(self) != 0) { | ||||||||
56 | return PyArray_DIMS(self)[0]; | ||||||||
57 | } else { | ||||||||
58 | PyErr_SetString(PyExc_TypeError, "len() of unsized object"); | ||||||||
59 | return -1; | ||||||||
60 | } | ||||||||
61 | } | ||||||||
62 | |||||||||
63 | |||||||||
64 | /* -------------------------------------------------------------- */ | ||||||||
65 | |||||||||
66 | |||||||||
67 | /* | ||||||||
68 | * Helper for `PyArray_MapIterSwapAxes` (and related), see its documentation. | ||||||||
69 | */ | ||||||||
70 | static void | ||||||||
71 | _get_transpose(int fancy_ndim, int consec, int ndim, int getmap, npy_intp *dims) | ||||||||
72 | { | ||||||||
73 | /* | ||||||||
74 | * For getting the array the tuple for transpose is | ||||||||
75 | * (n1,...,n1+n2-1,0,...,n1-1,n1+n2,...,n3-1) | ||||||||
76 | * n1 is the number of dimensions of the broadcast index array | ||||||||
77 | * n2 is the number of dimensions skipped at the start | ||||||||
78 | * n3 is the number of dimensions of the result | ||||||||
79 | */ | ||||||||
80 | |||||||||
81 | /* | ||||||||
82 | * For setting the array the tuple for transpose is | ||||||||
83 | * (n2,...,n1+n2-1,0,...,n2-1,n1+n2,...n3-1) | ||||||||
84 | */ | ||||||||
85 | int n1 = fancy_ndim; | ||||||||
86 | int n2 = consec; /* axes to insert at */ | ||||||||
87 | int n3 = ndim; | ||||||||
88 | |||||||||
89 | /* use n1 as the boundary if getting but n2 if setting */ | ||||||||
90 | int bnd = getmap ? n1 : n2; | ||||||||
91 | int val = bnd; | ||||||||
92 | int i = 0; | ||||||||
93 | while (val < n1 + n2) { | ||||||||
94 | dims[i++] = val++; | ||||||||
95 | } | ||||||||
96 | val = 0; | ||||||||
97 | while (val < bnd) { | ||||||||
98 | dims[i++] = val++; | ||||||||
99 | } | ||||||||
100 | val = n1 + n2; | ||||||||
101 | while (val < n3) { | ||||||||
102 | dims[i++] = val++; | ||||||||
103 | } | ||||||||
104 | } | ||||||||
105 | |||||||||
106 | |||||||||
107 | /*NUMPY_API | ||||||||
108 | * | ||||||||
109 | * Swap the axes to or from their inserted form. MapIter always puts the | ||||||||
110 | * advanced (array) indices first in the iteration. But if they are | ||||||||
111 | * consecutive, will insert/transpose them back before returning. | ||||||||
112 | * This is stored as `mit->consec != 0` (the place where they are inserted) | ||||||||
113 | * For assignments, the opposite happens: The values to be assigned are | ||||||||
114 | * transposed (getmap=1 instead of getmap=0). `getmap=0` and `getmap=1` | ||||||||
115 | * undo the other operation. | ||||||||
116 | */ | ||||||||
117 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) void | ||||||||
118 | PyArray_MapIterSwapAxes(PyArrayMapIterObject *mit, PyArrayObject **ret, int getmap) | ||||||||
119 | { | ||||||||
120 | PyObject *new; | ||||||||
121 | PyArray_Dims permute; | ||||||||
122 | npy_intp d[NPY_MAXDIMS32]; | ||||||||
123 | PyArrayObject *arr; | ||||||||
124 | |||||||||
125 | permute.ptr = d; | ||||||||
126 | permute.len = mit->nd; | ||||||||
127 | |||||||||
128 | /* | ||||||||
129 | * arr might not have the right number of dimensions | ||||||||
130 | * and need to be reshaped first by pre-pending ones | ||||||||
131 | */ | ||||||||
132 | arr = *ret; | ||||||||
133 | if (PyArray_NDIM(arr) != mit->nd) { | ||||||||
134 | for (int i = 1; i <= PyArray_NDIM(arr); i++) { | ||||||||
135 | permute.ptr[mit->nd-i] = PyArray_DIMS(arr)[PyArray_NDIM(arr)-i]; | ||||||||
136 | } | ||||||||
137 | for (int i = 0; i < mit->nd-PyArray_NDIM(arr); i++) { | ||||||||
138 | permute.ptr[i] = 1; | ||||||||
139 | } | ||||||||
140 | new = PyArray_Newshape(arr, &permute, NPY_ANYORDER); | ||||||||
141 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); | ||||||||
142 | *ret = (PyArrayObject *)new; | ||||||||
143 | if (new == NULL((void*)0)) { | ||||||||
144 | return; | ||||||||
145 | } | ||||||||
146 | } | ||||||||
147 | |||||||||
148 | _get_transpose(mit->nd_fancy, mit->consec, mit->nd, getmap, permute.ptr); | ||||||||
149 | |||||||||
150 | new = PyArray_Transpose(*ret, &permute); | ||||||||
151 | Py_DECREF(*ret)_Py_DECREF(((PyObject*)(*ret))); | ||||||||
152 | *ret = (PyArrayObject *)new; | ||||||||
153 | } | ||||||||
154 | |||||||||
155 | static NPY_INLINEinline void | ||||||||
156 | multi_DECREF(PyObject **objects, npy_intp n) | ||||||||
157 | { | ||||||||
158 | npy_intp i; | ||||||||
159 | for (i = 0; i < n; i++) { | ||||||||
160 | Py_DECREF(objects[i])_Py_DECREF(((PyObject*)(objects[i]))); | ||||||||
161 | } | ||||||||
162 | } | ||||||||
163 | |||||||||
164 | /** | ||||||||
165 | * Unpack a tuple into an array of new references. Returns the number of objects | ||||||||
166 | * unpacked. | ||||||||
167 | * | ||||||||
168 | * Useful if a tuple is being iterated over multiple times, or for a code path | ||||||||
169 | * that doesn't always want the overhead of allocating a tuple. | ||||||||
170 | */ | ||||||||
171 | static NPY_INLINEinline npy_intp | ||||||||
172 | unpack_tuple(PyTupleObject *index, PyObject **result, npy_intp result_n) | ||||||||
173 | { | ||||||||
174 | npy_intp n, i; | ||||||||
175 | n = PyTuple_GET_SIZE(index)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(index))))-> ob_size); | ||||||||
176 | if (n > result_n) { | ||||||||
177 | PyErr_SetString(PyExc_IndexError, | ||||||||
178 | "too many indices for array"); | ||||||||
179 | return -1; | ||||||||
180 | } | ||||||||
181 | for (i = 0; i < n; i++) { | ||||||||
182 | result[i] = PyTuple_GET_ITEM(index, i)((((void) (0)), (PyTupleObject *)(index))->ob_item[i]); | ||||||||
183 | Py_INCREF(result[i])_Py_INCREF(((PyObject*)(result[i]))); | ||||||||
184 | } | ||||||||
185 | return n; | ||||||||
186 | } | ||||||||
187 | |||||||||
188 | /* Unpack a single scalar index, taking a new reference to match unpack_tuple */ | ||||||||
189 | static NPY_INLINEinline npy_intp | ||||||||
190 | unpack_scalar(PyObject *index, PyObject **result, npy_intp NPY_UNUSED(result_n)(__NPY_UNUSED_TAGGEDresult_n) __attribute__ ((__unused__))) | ||||||||
191 | { | ||||||||
192 | Py_INCREF(index)_Py_INCREF(((PyObject*)(index))); | ||||||||
193 | result[0] = index; | ||||||||
194 | return 1; | ||||||||
195 | } | ||||||||
196 | |||||||||
197 | /** | ||||||||
198 | * Turn an index argument into a c-array of `PyObject *`s, one for each index. | ||||||||
199 | * | ||||||||
200 | * When a scalar is passed, this is written directly to the buffer. When a | ||||||||
201 | * tuple is passed, the tuple elements are unpacked into the buffer. | ||||||||
202 | * | ||||||||
203 | * When some other sequence is passed, this implements the following section | ||||||||
204 | * from the advanced indexing docs to decide whether to unpack or just write | ||||||||
205 | * one element: | ||||||||
206 | * | ||||||||
207 | * > In order to remain backward compatible with a common usage in Numeric, | ||||||||
208 | * > basic slicing is also initiated if the selection object is any non-ndarray | ||||||||
209 | * > sequence (such as a list) containing slice objects, the Ellipsis object, | ||||||||
210 | * > or the newaxis object, but not for integer arrays or other embedded | ||||||||
211 | * > sequences. | ||||||||
212 | * | ||||||||
213 | * It might be worth deprecating this behaviour (gh-4434), in which case the | ||||||||
214 | * entire function should become a simple check of PyTuple_Check. | ||||||||
215 | * | ||||||||
216 | * @param index The index object, which may or may not be a tuple. This is | ||||||||
217 | * a borrowed reference. | ||||||||
218 | * @param result An empty buffer of PyObject* to write each index component | ||||||||
219 | * to. The references written are new. | ||||||||
220 | * @param result_n The length of the result buffer | ||||||||
221 | * | ||||||||
222 | * @returns The number of items in `result`, or -1 if an error occurred. | ||||||||
223 | * The entries in `result` at and beyond this index should be | ||||||||
224 | * assumed to contain garbage, even if they were initialized | ||||||||
225 | * to NULL, so are not safe to Py_XDECREF. Use multi_DECREF to | ||||||||
226 | * dispose of them. | ||||||||
227 | */ | ||||||||
228 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) npy_intp | ||||||||
229 | unpack_indices(PyObject *index, PyObject **result, npy_intp result_n) | ||||||||
230 | { | ||||||||
231 | npy_intp n, i; | ||||||||
232 | npy_bool commit_to_unpack; | ||||||||
233 | |||||||||
234 | /* Fast route for passing a tuple */ | ||||||||
235 | if (PyTuple_CheckExact(index)((((PyObject*)(index))->ob_type) == &PyTuple_Type)) { | ||||||||
236 | return unpack_tuple((PyTupleObject *)index, result, result_n); | ||||||||
237 | } | ||||||||
238 | |||||||||
239 | /* Obvious single-entry cases */ | ||||||||
240 | if (0 /* to aid macros below */ | ||||||||
241 | || PyLong_CheckExact(index)((((PyObject*)(index))->ob_type) == &PyLong_Type) | ||||||||
242 | || index == Py_None(&_Py_NoneStruct) | ||||||||
243 | || PySlice_Check(index)((((PyObject*)(index))->ob_type) == &PySlice_Type) | ||||||||
244 | || PyArray_Check(index)((((PyObject*)(index))->ob_type) == (&PyArray_Type) || PyType_IsSubtype((((PyObject*)(index))->ob_type), (&PyArray_Type ))) | ||||||||
245 | || !PySequence_Check(index) | ||||||||
246 | || PyUnicode_Check(index)((((((PyObject*)(index))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | ||||||||
247 | |||||||||
248 | return unpack_scalar(index, result, result_n); | ||||||||
249 | } | ||||||||
250 | |||||||||
251 | /* | ||||||||
252 | * Passing a tuple subclass - coerce to the base type. This incurs an | ||||||||
253 | * allocation, but doesn't need to be a fast path anyway | ||||||||
254 | */ | ||||||||
255 | if (PyTuple_Check(index)((((((PyObject*)(index))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | ||||||||
256 | PyTupleObject *tup = (PyTupleObject *) PySequence_Tuple(index); | ||||||||
257 | if (tup == NULL((void*)0)) { | ||||||||
258 | return -1; | ||||||||
259 | } | ||||||||
260 | n = unpack_tuple(tup, result, result_n); | ||||||||
261 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | ||||||||
262 | return n; | ||||||||
263 | } | ||||||||
264 | |||||||||
265 | /* | ||||||||
266 | * At this point, we're left with a non-tuple, non-array, sequence: | ||||||||
267 | * typically, a list. We use some somewhat-arbitrary heuristics from here | ||||||||
268 | * onwards to decided whether to treat that list as a single index, or a | ||||||||
269 | * list of indices. | ||||||||
270 | */ | ||||||||
271 | |||||||||
272 | /* if len fails, treat like a scalar */ | ||||||||
273 | n = PySequence_Size(index); | ||||||||
274 | if (n < 0) { | ||||||||
275 | PyErr_Clear(); | ||||||||
276 | return unpack_scalar(index, result, result_n); | ||||||||
277 | } | ||||||||
278 | |||||||||
279 | /* | ||||||||
280 | * Backwards compatibility only takes effect for short sequences - otherwise | ||||||||
281 | * we treat it like any other scalar. | ||||||||
282 | * | ||||||||
283 | * Sequences < NPY_MAXDIMS with any slice objects | ||||||||
284 | * or newaxis, Ellipsis or other arrays or sequences | ||||||||
285 | * embedded, are considered equivalent to an indexing | ||||||||
286 | * tuple. (`a[[[1,2], [3,4]]] == a[[1,2], [3,4]]`) | ||||||||
287 | */ | ||||||||
288 | if (n >= NPY_MAXDIMS32) { | ||||||||
289 | return unpack_scalar(index, result, result_n); | ||||||||
290 | } | ||||||||
291 | |||||||||
292 | /* In case we change result_n elsewhere */ | ||||||||
293 | assert(n <= result_n)((void) (0)); | ||||||||
294 | |||||||||
295 | /* | ||||||||
296 | * Some other type of short sequence - assume we should unpack it like a | ||||||||
297 | * tuple, and then decide whether that was actually necessary. | ||||||||
298 | */ | ||||||||
299 | commit_to_unpack = 0; | ||||||||
300 | for (i = 0; i < n; i++) { | ||||||||
301 | PyObject *tmp_obj = result[i] = PySequence_GetItem(index, i); | ||||||||
302 | |||||||||
303 | if (commit_to_unpack) { | ||||||||
304 | /* propagate errors */ | ||||||||
305 | if (tmp_obj == NULL((void*)0)) { | ||||||||
306 | goto fail; | ||||||||
307 | } | ||||||||
308 | } | ||||||||
309 | else { | ||||||||
310 | /* | ||||||||
311 | * if getitem fails (unusual) before we've committed, then stop | ||||||||
312 | * unpacking | ||||||||
313 | */ | ||||||||
314 | if (tmp_obj == NULL((void*)0)) { | ||||||||
315 | PyErr_Clear(); | ||||||||
316 | break; | ||||||||
317 | } | ||||||||
318 | |||||||||
319 | /* decide if we should treat this sequence like a tuple */ | ||||||||
320 | if (PyArray_Check(tmp_obj)((((PyObject*)(tmp_obj))->ob_type) == (&PyArray_Type) || PyType_IsSubtype((((PyObject*)(tmp_obj))->ob_type), (& PyArray_Type))) | ||||||||
321 | || PySequence_Check(tmp_obj) | ||||||||
322 | || PySlice_Check(tmp_obj)((((PyObject*)(tmp_obj))->ob_type) == &PySlice_Type) | ||||||||
323 | || tmp_obj == Py_Ellipsis(&_Py_EllipsisObject) | ||||||||
324 | || tmp_obj == Py_None(&_Py_NoneStruct)) { | ||||||||
325 | if (DEPRECATE_FUTUREWARNING(PyErr_WarnEx(PyExc_FutureWarning,"Using a non-tuple sequence for multidimensional " "indexing is deprecated; use `arr[tuple(seq)]` " "instead of `arr[seq]`. In the future this will be " "interpreted as an array index, `arr[np.array(seq)]`, " "which will result either in an error or a different " "result.",1) | ||||||||
326 | "Using a non-tuple sequence for multidimensional "PyErr_WarnEx(PyExc_FutureWarning,"Using a non-tuple sequence for multidimensional " "indexing is deprecated; use `arr[tuple(seq)]` " "instead of `arr[seq]`. In the future this will be " "interpreted as an array index, `arr[np.array(seq)]`, " "which will result either in an error or a different " "result.",1) | ||||||||
327 | "indexing is deprecated; use `arr[tuple(seq)]` "PyErr_WarnEx(PyExc_FutureWarning,"Using a non-tuple sequence for multidimensional " "indexing is deprecated; use `arr[tuple(seq)]` " "instead of `arr[seq]`. In the future this will be " "interpreted as an array index, `arr[np.array(seq)]`, " "which will result either in an error or a different " "result.",1) | ||||||||
328 | "instead of `arr[seq]`. In the future this will be "PyErr_WarnEx(PyExc_FutureWarning,"Using a non-tuple sequence for multidimensional " "indexing is deprecated; use `arr[tuple(seq)]` " "instead of `arr[seq]`. In the future this will be " "interpreted as an array index, `arr[np.array(seq)]`, " "which will result either in an error or a different " "result.",1) | ||||||||
329 | "interpreted as an array index, `arr[np.array(seq)]`, "PyErr_WarnEx(PyExc_FutureWarning,"Using a non-tuple sequence for multidimensional " "indexing is deprecated; use `arr[tuple(seq)]` " "instead of `arr[seq]`. In the future this will be " "interpreted as an array index, `arr[np.array(seq)]`, " "which will result either in an error or a different " "result.",1) | ||||||||
330 | "which will result either in an error or a different "PyErr_WarnEx(PyExc_FutureWarning,"Using a non-tuple sequence for multidimensional " "indexing is deprecated; use `arr[tuple(seq)]` " "instead of `arr[seq]`. In the future this will be " "interpreted as an array index, `arr[np.array(seq)]`, " "which will result either in an error or a different " "result.",1) | ||||||||
331 | "result.")PyErr_WarnEx(PyExc_FutureWarning,"Using a non-tuple sequence for multidimensional " "indexing is deprecated; use `arr[tuple(seq)]` " "instead of `arr[seq]`. In the future this will be " "interpreted as an array index, `arr[np.array(seq)]`, " "which will result either in an error or a different " "result.",1) < 0) { | ||||||||
332 | i++; /* since loop update doesn't run */ | ||||||||
333 | goto fail; | ||||||||
334 | } | ||||||||
335 | commit_to_unpack = 1; | ||||||||
336 | } | ||||||||
337 | } | ||||||||
338 | } | ||||||||
339 | |||||||||
340 | /* unpacking was the right thing to do, and we already did it */ | ||||||||
341 | if (commit_to_unpack) { | ||||||||
342 | return n; | ||||||||
343 | } | ||||||||
344 | /* got to the end, never found an indication that we should have unpacked */ | ||||||||
345 | else { | ||||||||
346 | /* we partially filled result, so empty it first */ | ||||||||
347 | multi_DECREF(result, i); | ||||||||
348 | return unpack_scalar(index, result, result_n); | ||||||||
349 | } | ||||||||
350 | |||||||||
351 | fail: | ||||||||
352 | multi_DECREF(result, i); | ||||||||
353 | return -1; | ||||||||
354 | } | ||||||||
355 | |||||||||
356 | /** | ||||||||
357 | * Prepare an npy_index_object from the python slicing object. | ||||||||
358 | * | ||||||||
359 | * This function handles all index preparations with the exception | ||||||||
360 | * of field access. It fills the array of index_info structs correctly. | ||||||||
361 | * It already handles the boolean array special case for fancy indexing, | ||||||||
362 | * i.e. if the index type is boolean, it is exactly one matching boolean | ||||||||
363 | * array. If the index type is fancy, the boolean array is already | ||||||||
364 | * converted to integer arrays. There is (as before) no checking of the | ||||||||
365 | * boolean dimension. | ||||||||
366 | * | ||||||||
367 | * Checks everything but the bounds. | ||||||||
368 | * | ||||||||
369 | * @param the array being indexed | ||||||||
370 | * @param the index object | ||||||||
371 | * @param index info struct being filled (size of NPY_MAXDIMS * 2 + 1) | ||||||||
372 | * @param number of indices found | ||||||||
373 | * @param dimension of the indexing result | ||||||||
374 | * @param dimension of the fancy/advanced indices part | ||||||||
375 | * @param whether to allow the boolean special case | ||||||||
376 | * | ||||||||
377 | * @returns the index_type or -1 on failure and fills the number of indices. | ||||||||
378 | */ | ||||||||
379 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||
380 | prepare_index(PyArrayObject *self, PyObject *index, | ||||||||
381 | npy_index_info *indices, | ||||||||
382 | int *num, int *ndim, int *out_fancy_ndim, int allow_boolean) | ||||||||
383 | { | ||||||||
384 | int new_ndim, fancy_ndim, used_ndim, index_ndim; | ||||||||
385 | int curr_idx, get_idx; | ||||||||
386 | |||||||||
387 | int i; | ||||||||
388 | npy_intp n; | ||||||||
389 | |||||||||
390 | PyObject *obj = NULL((void*)0); | ||||||||
391 | PyArrayObject *arr; | ||||||||
392 | |||||||||
393 | int index_type = 0; | ||||||||
394 | int ellipsis_pos = -1; | ||||||||
395 | |||||||||
396 | /* | ||||||||
397 | * The choice of only unpacking `2*NPY_MAXDIMS` items is historic. | ||||||||
398 | * The longest "reasonable" index that produces a result of <= 32 dimensions | ||||||||
399 | * is `(0,)*np.MAXDIMS + (None,)*np.MAXDIMS`. Longer indices can exist, but | ||||||||
400 | * are uncommon. | ||||||||
401 | */ | ||||||||
402 | PyObject *raw_indices[NPY_MAXDIMS32*2]; | ||||||||
403 | |||||||||
404 | index_ndim = unpack_indices(index, raw_indices, NPY_MAXDIMS32*2); | ||||||||
405 | if (index_ndim == -1) { | ||||||||
| |||||||||
406 | return -1; | ||||||||
407 | } | ||||||||
408 | |||||||||
409 | /* | ||||||||
410 | * Parse all indices into the `indices` array of index_info structs | ||||||||
411 | */ | ||||||||
412 | used_ndim = 0; | ||||||||
413 | new_ndim = 0; | ||||||||
414 | fancy_ndim = 0; | ||||||||
415 | get_idx = 0; | ||||||||
416 | curr_idx = 0; | ||||||||
417 | |||||||||
418 | while (get_idx < index_ndim) { | ||||||||
419 | if (curr_idx > NPY_MAXDIMS32 * 2) { | ||||||||
420 | PyErr_SetString(PyExc_IndexError, | ||||||||
421 | "too many indices for array"); | ||||||||
422 | goto failed_building_indices; | ||||||||
423 | } | ||||||||
424 | |||||||||
425 | obj = raw_indices[get_idx++]; | ||||||||
426 | |||||||||
427 | /**** Try the cascade of possible indices ****/ | ||||||||
428 | |||||||||
429 | /* Index is an ellipsis (`...`) */ | ||||||||
430 | if (obj == Py_Ellipsis(&_Py_EllipsisObject)) { | ||||||||
431 | /* At most one ellipsis in an index */ | ||||||||
432 | if (index_type & HAS_ELLIPSIS) { | ||||||||
433 | PyErr_Format(PyExc_IndexError, | ||||||||
434 | "an index can only have a single ellipsis ('...')"); | ||||||||
435 | goto failed_building_indices; | ||||||||
436 | } | ||||||||
437 | index_type |= HAS_ELLIPSIS; | ||||||||
438 | indices[curr_idx].type = HAS_ELLIPSIS; | ||||||||
439 | indices[curr_idx].object = NULL((void*)0); | ||||||||
440 | /* number of slices it is worth, won't update if it is 0: */ | ||||||||
441 | indices[curr_idx].value = 0; | ||||||||
442 | |||||||||
443 | ellipsis_pos = curr_idx; | ||||||||
444 | /* the used and new ndim will be found later */ | ||||||||
445 | used_ndim += 0; | ||||||||
446 | new_ndim += 0; | ||||||||
447 | curr_idx += 1; | ||||||||
448 | continue; | ||||||||
449 | } | ||||||||
450 | |||||||||
451 | /* Index is np.newaxis/None */ | ||||||||
452 | else if (obj == Py_None(&_Py_NoneStruct)) { | ||||||||
453 | index_type |= HAS_NEWAXIS; | ||||||||
454 | |||||||||
455 | indices[curr_idx].type = HAS_NEWAXIS; | ||||||||
456 | indices[curr_idx].object = NULL((void*)0); | ||||||||
457 | |||||||||
458 | used_ndim += 0; | ||||||||
459 | new_ndim += 1; | ||||||||
460 | curr_idx += 1; | ||||||||
461 | continue; | ||||||||
462 | } | ||||||||
463 | |||||||||
464 | /* Index is a slice object. */ | ||||||||
465 | else if (PySlice_Check(obj)((((PyObject*)(obj))->ob_type) == &PySlice_Type)) { | ||||||||
466 | index_type |= HAS_SLICE; | ||||||||
467 | |||||||||
468 | Py_INCREF(obj)_Py_INCREF(((PyObject*)(obj))); | ||||||||
469 | indices[curr_idx].object = obj; | ||||||||
470 | indices[curr_idx].type = HAS_SLICE; | ||||||||
471 | used_ndim += 1; | ||||||||
472 | new_ndim += 1; | ||||||||
473 | curr_idx += 1; | ||||||||
474 | continue; | ||||||||
475 | } | ||||||||
476 | |||||||||
477 | /* | ||||||||
478 | * Special case to allow 0-d boolean indexing with scalars. | ||||||||
479 | * Should be removed after boolean as integer deprecation. | ||||||||
480 | * Since this is always an error if it was not a boolean, we can | ||||||||
481 | * allow the 0-d special case before the rest. | ||||||||
482 | */ | ||||||||
483 | else if (PyArray_NDIM(self) != 0) { | ||||||||
484 | /* | ||||||||
485 | * Single integer index, there are two cases here. | ||||||||
486 | * It could be an array, a 0-d array is handled | ||||||||
487 | * a bit weird however, so need to special case it. | ||||||||
488 | * | ||||||||
489 | * Check for integers first, purely for performance | ||||||||
490 | */ | ||||||||
491 | if (PyLong_CheckExact(obj)((((PyObject*)(obj))->ob_type) == &PyLong_Type) || !PyArray_Check(obj)((((PyObject*)(obj))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(obj))->ob_type), (&PyArray_Type)))) { | ||||||||
492 | npy_intp ind = PyArray_PyIntAsIntp(obj); | ||||||||
493 | |||||||||
494 | if (error_converting(ind)(((ind) == -1) && PyErr_Occurred())) { | ||||||||
495 | PyErr_Clear(); | ||||||||
496 | } | ||||||||
497 | else { | ||||||||
498 | index_type |= HAS_INTEGER; | ||||||||
499 | indices[curr_idx].object = NULL((void*)0); | ||||||||
500 | indices[curr_idx].value = ind; | ||||||||
501 | indices[curr_idx].type = HAS_INTEGER; | ||||||||
502 | used_ndim += 1; | ||||||||
503 | new_ndim += 0; | ||||||||
504 | curr_idx += 1; | ||||||||
505 | continue; | ||||||||
506 | } | ||||||||
507 | } | ||||||||
508 | } | ||||||||
509 | |||||||||
510 | /* | ||||||||
511 | * At this point, we must have an index array (or array-like). | ||||||||
512 | * It might still be a (purely) bool special case, a 0-d integer | ||||||||
513 | * array (an array scalar) or something invalid. | ||||||||
514 | */ | ||||||||
515 | |||||||||
516 | if (!PyArray_Check(obj)((((PyObject*)(obj))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(obj))->ob_type), (&PyArray_Type)))) { | ||||||||
517 | PyArrayObject *tmp_arr; | ||||||||
518 | tmp_arr = (PyArrayObject *)PyArray_FROM_O(obj)PyArray_FromAny(obj, ((void*)0), 0, 0, 0, ((void*)0)); | ||||||||
519 | if (tmp_arr == NULL((void*)0)) { | ||||||||
520 | /* TODO: Should maybe replace the error here? */ | ||||||||
521 | goto failed_building_indices; | ||||||||
522 | } | ||||||||
523 | |||||||||
524 | /* | ||||||||
525 | * For example an empty list can be cast to an integer array, | ||||||||
526 | * however it will default to a float one. | ||||||||
527 | */ | ||||||||
528 | if (PyArray_SIZE(tmp_arr)PyArray_MultiplyList(PyArray_DIMS(tmp_arr), PyArray_NDIM(tmp_arr )) == 0) { | ||||||||
529 | PyArray_Descr *indtype = PyArray_DescrFromType(NPY_INTPNPY_LONG); | ||||||||
530 | |||||||||
531 | arr = (PyArrayObject *)PyArray_FromArray(tmp_arr, indtype, | ||||||||
532 | NPY_ARRAY_FORCECAST0x0010); | ||||||||
533 | Py_DECREF(tmp_arr)_Py_DECREF(((PyObject*)(tmp_arr))); | ||||||||
534 | if (arr == NULL((void*)0)) { | ||||||||
535 | goto failed_building_indices; | ||||||||
536 | } | ||||||||
537 | } | ||||||||
538 | else { | ||||||||
539 | arr = tmp_arr; | ||||||||
540 | } | ||||||||
541 | } | ||||||||
542 | else { | ||||||||
543 | Py_INCREF(obj)_Py_INCREF(((PyObject*)(obj))); | ||||||||
544 | arr = (PyArrayObject *)obj; | ||||||||
545 | } | ||||||||
546 | |||||||||
547 | /* Check if the array is valid and fill the information */ | ||||||||
548 | if (PyArray_ISBOOL(arr)((PyArray_TYPE(arr)) == NPY_BOOL)) { | ||||||||
549 | /* | ||||||||
550 | * There are two types of boolean indices (which are equivalent, | ||||||||
551 | * for the most part though). A single boolean index of matching | ||||||||
552 | * shape is a boolean index. If this is not the case, it is | ||||||||
553 | * instead expanded into (multiple) integer array indices. | ||||||||
554 | */ | ||||||||
555 | PyArrayObject *nonzero_result[NPY_MAXDIMS32]; | ||||||||
556 | |||||||||
557 | if ((index_ndim
| ||||||||
558 | /* | ||||||||
559 | * If shapes match exactly, this can be optimized as a single | ||||||||
560 | * boolean index. When the dimensions are identical but the shapes are not, | ||||||||
561 | * this is always an error. The check ensures that these errors are raised | ||||||||
562 | * and match those of the generic path. | ||||||||
563 | */ | ||||||||
564 | if ((PyArray_NDIM(arr) == PyArray_NDIM(self)) | ||||||||
565 | && PyArray_CompareLists(PyArray_DIMS(arr), | ||||||||
566 | PyArray_DIMS(self), | ||||||||
567 | PyArray_NDIM(arr))) { | ||||||||
568 | |||||||||
569 | index_type = HAS_BOOL; | ||||||||
570 | indices[curr_idx].type = HAS_BOOL; | ||||||||
571 | indices[curr_idx].object = (PyObject *)arr; | ||||||||
572 | |||||||||
573 | /* keep track anyway, just to be complete */ | ||||||||
574 | used_ndim = PyArray_NDIM(self); | ||||||||
575 | fancy_ndim = PyArray_NDIM(self); | ||||||||
576 | curr_idx += 1; | ||||||||
577 | break; | ||||||||
578 | } | ||||||||
579 | } | ||||||||
580 | |||||||||
581 | if (PyArray_NDIM(arr) == 0) { | ||||||||
582 | /* | ||||||||
583 | * This can actually be well defined. A new axis is added, | ||||||||
584 | * but at the same time no axis is "used". So if we have True, | ||||||||
585 | * we add a new axis (a bit like with np.newaxis). If it is | ||||||||
586 | * False, we add a new axis, but this axis has 0 entries. | ||||||||
587 | */ | ||||||||
588 | |||||||||
589 | index_type |= HAS_FANCY; | ||||||||
590 | indices[curr_idx].type = HAS_0D_BOOL; | ||||||||
591 | |||||||||
592 | /* TODO: This can't fail, right? Is there a faster way? */ | ||||||||
593 | if (PyObject_IsTrue((PyObject *)arr)) { | ||||||||
594 | n = 1; | ||||||||
595 | } | ||||||||
596 | else { | ||||||||
597 | n = 0; | ||||||||
598 | } | ||||||||
599 | indices[curr_idx].value = n; | ||||||||
600 | indices[curr_idx].object = PyArray_Zeros(1, &n, | ||||||||
601 | PyArray_DescrFromType(NPY_INTPNPY_LONG), 0); | ||||||||
602 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); | ||||||||
603 | |||||||||
604 | if (indices[curr_idx].object == NULL((void*)0)) { | ||||||||
605 | goto failed_building_indices; | ||||||||
606 | } | ||||||||
607 | |||||||||
608 | used_ndim += 0; | ||||||||
609 | if (fancy_ndim < 1) { | ||||||||
610 | fancy_ndim = 1; | ||||||||
611 | } | ||||||||
612 | curr_idx += 1; | ||||||||
613 | continue; | ||||||||
614 | } | ||||||||
615 | |||||||||
616 | /* Convert the boolean array into multiple integer ones */ | ||||||||
617 | n = _nonzero_indices((PyObject *)arr, nonzero_result); | ||||||||
618 | |||||||||
619 | if (n < 0) { | ||||||||
620 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); | ||||||||
621 | goto failed_building_indices; | ||||||||
622 | } | ||||||||
623 | |||||||||
624 | /* Check that we will not run out of indices to store new ones */ | ||||||||
625 | if (curr_idx + n >= NPY_MAXDIMS32 * 2) { | ||||||||
626 | PyErr_SetString(PyExc_IndexError, | ||||||||
627 | "too many indices for array"); | ||||||||
628 | for (i=0; i < n; i++) { | ||||||||
629 | Py_DECREF(nonzero_result[i])_Py_DECREF(((PyObject*)(nonzero_result[i]))); | ||||||||
630 | } | ||||||||
631 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); | ||||||||
632 | goto failed_building_indices; | ||||||||
633 | } | ||||||||
634 | |||||||||
635 | /* Add the arrays from the nonzero result to the index */ | ||||||||
636 | index_type |= HAS_FANCY; | ||||||||
637 | for (i=0; i < n; i++) { | ||||||||
638 | indices[curr_idx].type = HAS_FANCY; | ||||||||
639 | indices[curr_idx].value = PyArray_DIM(arr, i); | ||||||||
640 | indices[curr_idx].object = (PyObject *)nonzero_result[i]; | ||||||||
641 | |||||||||
642 | used_ndim += 1; | ||||||||
643 | curr_idx += 1; | ||||||||
644 | } | ||||||||
645 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); | ||||||||
646 | |||||||||
647 | /* All added indices have 1 dimension */ | ||||||||
648 | if (fancy_ndim < 1) { | ||||||||
649 | fancy_ndim = 1; | ||||||||
650 | } | ||||||||
651 | continue; | ||||||||
652 | } | ||||||||
653 | |||||||||
654 | /* Normal case of an integer array */ | ||||||||
655 | else if (PyArray_ISINTEGER(arr)(((PyArray_TYPE(arr)) >= NPY_BYTE) && ((PyArray_TYPE (arr)) <= NPY_ULONGLONG))) { | ||||||||
656 | if (PyArray_NDIM(arr) == 0) { | ||||||||
657 | /* | ||||||||
658 | * A 0-d integer array is an array scalar and can | ||||||||
659 | * be dealt with the HAS_SCALAR_ARRAY flag. | ||||||||
660 | * We could handle 0-d arrays early on, but this makes | ||||||||
661 | * sure that array-likes or odder arrays are always | ||||||||
662 | * handled right. | ||||||||
663 | */ | ||||||||
664 | npy_intp ind = PyArray_PyIntAsIntp((PyObject *)arr); | ||||||||
665 | |||||||||
666 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); | ||||||||
667 | if (error_converting(ind)(((ind) == -1) && PyErr_Occurred())) { | ||||||||
668 | goto failed_building_indices; | ||||||||
669 | } | ||||||||
670 | else { | ||||||||
671 | index_type |= (HAS_INTEGER | HAS_SCALAR_ARRAY); | ||||||||
672 | indices[curr_idx].object = NULL((void*)0); | ||||||||
673 | indices[curr_idx].value = ind; | ||||||||
674 | indices[curr_idx].type = HAS_INTEGER; | ||||||||
675 | used_ndim += 1; | ||||||||
676 | new_ndim += 0; | ||||||||
677 | curr_idx += 1; | ||||||||
678 | continue; | ||||||||
679 | } | ||||||||
680 | } | ||||||||
681 | |||||||||
682 | index_type |= HAS_FANCY; | ||||||||
683 | indices[curr_idx].type = HAS_FANCY; | ||||||||
684 | indices[curr_idx].value = -1; | ||||||||
685 | indices[curr_idx].object = (PyObject *)arr; | ||||||||
686 | |||||||||
687 | used_ndim += 1; | ||||||||
688 | if (fancy_ndim < PyArray_NDIM(arr)) { | ||||||||
689 | fancy_ndim = PyArray_NDIM(arr); | ||||||||
690 | } | ||||||||
691 | curr_idx += 1; | ||||||||
692 | continue; | ||||||||
693 | } | ||||||||
694 | |||||||||
695 | /* | ||||||||
696 | * The array does not have a valid type. | ||||||||
697 | */ | ||||||||
698 | if ((PyObject *)arr == obj) { | ||||||||
699 | /* The input was an array already */ | ||||||||
700 | PyErr_SetString(PyExc_IndexError, | ||||||||
701 | "arrays used as indices must be of integer (or boolean) type"); | ||||||||
702 | } | ||||||||
703 | else { | ||||||||
704 | /* The input was not an array, so give a general error message */ | ||||||||
705 | PyErr_SetString(PyExc_IndexError, | ||||||||
706 | "only integers, slices (`:`), ellipsis (`...`), " | ||||||||
707 | "numpy.newaxis (`None`) and integer or boolean " | ||||||||
708 | "arrays are valid indices"); | ||||||||
709 | } | ||||||||
710 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); | ||||||||
711 | goto failed_building_indices; | ||||||||
712 | } | ||||||||
713 | |||||||||
714 | /* | ||||||||
715 | * Compare dimension of the index to the real ndim. this is | ||||||||
716 | * to find the ellipsis value or append an ellipsis if necessary. | ||||||||
717 | */ | ||||||||
718 | if (used_ndim < PyArray_NDIM(self)) { | ||||||||
719 | if (index_type & HAS_ELLIPSIS) { | ||||||||
720 | indices[ellipsis_pos].value = PyArray_NDIM(self) - used_ndim; | ||||||||
721 | used_ndim = PyArray_NDIM(self); | ||||||||
722 | new_ndim += indices[ellipsis_pos].value; | ||||||||
723 | } | ||||||||
724 | else { | ||||||||
725 | /* | ||||||||
726 | * There is no ellipsis yet, but it is not a full index | ||||||||
727 | * so we append an ellipsis to the end. | ||||||||
728 | */ | ||||||||
729 | index_type |= HAS_ELLIPSIS; | ||||||||
730 | indices[curr_idx].object = NULL((void*)0); | ||||||||
731 | indices[curr_idx].type = HAS_ELLIPSIS; | ||||||||
732 | indices[curr_idx].value = PyArray_NDIM(self) - used_ndim; | ||||||||
733 | ellipsis_pos = curr_idx; | ||||||||
734 | |||||||||
735 | used_ndim = PyArray_NDIM(self); | ||||||||
736 | new_ndim += indices[curr_idx].value; | ||||||||
737 | curr_idx += 1; | ||||||||
738 | } | ||||||||
739 | } | ||||||||
740 | else if (used_ndim > PyArray_NDIM(self)) { | ||||||||
741 | PyErr_Format(PyExc_IndexError, | ||||||||
742 | "too many indices for array: " | ||||||||
743 | "array is %d-dimensional, but %d were indexed", | ||||||||
744 | PyArray_NDIM(self), | ||||||||
745 | used_ndim); | ||||||||
746 | goto failed_building_indices; | ||||||||
747 | } | ||||||||
748 | else if (index_ndim == 0) { | ||||||||
749 | /* | ||||||||
750 | * 0-d index into 0-d array, i.e. array[()] | ||||||||
751 | * We consider this an integer index. Which means it will return | ||||||||
752 | * the scalar. | ||||||||
753 | * This makes sense, because then array[...] gives | ||||||||
754 | * an array and array[()] gives the scalar. | ||||||||
755 | */ | ||||||||
756 | used_ndim = 0; | ||||||||
757 | index_type = HAS_INTEGER; | ||||||||
758 | } | ||||||||
759 | |||||||||
760 | /* HAS_SCALAR_ARRAY requires cleaning up the index_type */ | ||||||||
761 | if (index_type & HAS_SCALAR_ARRAY) { | ||||||||
762 | /* clear as info is unnecessary and makes life harder later */ | ||||||||
763 | if (index_type & HAS_FANCY) { | ||||||||
764 | index_type -= HAS_SCALAR_ARRAY; | ||||||||
765 | } | ||||||||
766 | /* A full integer index sees array scalars as part of itself */ | ||||||||
767 | else if (index_type == (HAS_INTEGER | HAS_SCALAR_ARRAY)) { | ||||||||
768 | index_type -= HAS_SCALAR_ARRAY; | ||||||||
769 | } | ||||||||
770 | } | ||||||||
771 | |||||||||
772 | /* | ||||||||
773 | * At this point indices are all set correctly, no bounds checking | ||||||||
774 | * has been made and the new array may still have more dimensions | ||||||||
775 | * than is possible and boolean indexing arrays may have an incorrect shape. | ||||||||
776 | * | ||||||||
777 | * Check this now so we do not have to worry about it later. | ||||||||
778 | * It can happen for fancy indexing or with newaxis. | ||||||||
779 | * This means broadcasting errors in the case of too many dimensions | ||||||||
780 | * take less priority. | ||||||||
781 | */ | ||||||||
782 | if (index_type & (HAS_NEWAXIS | HAS_FANCY)) { | ||||||||
783 | if (new_ndim + fancy_ndim > NPY_MAXDIMS32) { | ||||||||
784 | PyErr_Format(PyExc_IndexError, | ||||||||
785 | "number of dimensions must be within [0, %d], " | ||||||||
786 | "indexing result would have %d", | ||||||||
787 | NPY_MAXDIMS32, (new_ndim + fancy_ndim)); | ||||||||
788 | goto failed_building_indices; | ||||||||
789 | } | ||||||||
790 | |||||||||
791 | /* | ||||||||
792 | * If we had a fancy index, we may have had a boolean array index. | ||||||||
793 | * So check if this had the correct shape now that we can find out | ||||||||
794 | * which axes it acts on. | ||||||||
795 | */ | ||||||||
796 | used_ndim = 0; | ||||||||
797 | for (i = 0; i < curr_idx; i++) { | ||||||||
798 | if ((indices[i].type == HAS_FANCY) && indices[i].value > 0) { | ||||||||
799 | if (indices[i].value != PyArray_DIM(self, used_ndim)) { | ||||||||
800 | char err_msg[174]; | ||||||||
801 | |||||||||
802 | PyOS_snprintf(err_msg, sizeof(err_msg), | ||||||||
803 | "boolean index did not match indexed array along " | ||||||||
804 | "dimension %d; dimension is %" NPY_INTP_FMT"ld" | ||||||||
805 | " but corresponding boolean dimension is %" NPY_INTP_FMT"ld", | ||||||||
806 | used_ndim, PyArray_DIM(self, used_ndim), | ||||||||
807 | indices[i].value); | ||||||||
808 | PyErr_SetString(PyExc_IndexError, err_msg); | ||||||||
809 | goto failed_building_indices; | ||||||||
810 | } | ||||||||
811 | } | ||||||||
812 | |||||||||
813 | if (indices[i].type == HAS_ELLIPSIS) { | ||||||||
814 | used_ndim += indices[i].value; | ||||||||
815 | } | ||||||||
816 | else if ((indices[i].type == HAS_NEWAXIS) || | ||||||||
817 | (indices[i].type == HAS_0D_BOOL)) { | ||||||||
818 | used_ndim += 0; | ||||||||
819 | } | ||||||||
820 | else { | ||||||||
821 | used_ndim += 1; | ||||||||
822 | } | ||||||||
823 | } | ||||||||
824 | } | ||||||||
825 | |||||||||
826 | *num = curr_idx; | ||||||||
827 | *ndim = new_ndim + fancy_ndim; | ||||||||
828 | *out_fancy_ndim = fancy_ndim; | ||||||||
829 | |||||||||
830 | multi_DECREF(raw_indices, index_ndim); | ||||||||
831 | |||||||||
832 | return index_type; | ||||||||
833 | |||||||||
834 | failed_building_indices: | ||||||||
835 | for (i=0; i < curr_idx; i++) { | ||||||||
836 | Py_XDECREF(indices[i].object)_Py_XDECREF(((PyObject*)(indices[i].object))); | ||||||||
837 | } | ||||||||
838 | multi_DECREF(raw_indices, index_ndim); | ||||||||
839 | return -1; | ||||||||
840 | } | ||||||||
841 | |||||||||
842 | |||||||||
843 | /** | ||||||||
844 | * Check if self has memory overlap with one of the index arrays, or with extra_op. | ||||||||
845 | * | ||||||||
846 | * @returns 1 if memory overlap found, 0 if not. | ||||||||
847 | */ | ||||||||
848 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||
849 | index_has_memory_overlap(PyArrayObject *self, | ||||||||
850 | int index_type, npy_index_info *indices, int num, | ||||||||
851 | PyObject *extra_op) | ||||||||
852 | { | ||||||||
853 | int i; | ||||||||
854 | |||||||||
855 | if (index_type & (HAS_FANCY | HAS_BOOL)) { | ||||||||
856 | for (i = 0; i < num; ++i) { | ||||||||
857 | if (indices[i].object != NULL((void*)0) && | ||||||||
858 | PyArray_Check(indices[i].object)((((PyObject*)(indices[i].object))->ob_type) == (&PyArray_Type ) || PyType_IsSubtype((((PyObject*)(indices[i].object))->ob_type ), (&PyArray_Type))) && | ||||||||
859 | solve_may_share_memory(self, | ||||||||
860 | (PyArrayObject *)indices[i].object, | ||||||||
861 | 1) != 0) { | ||||||||
862 | return 1; | ||||||||
863 | } | ||||||||
864 | } | ||||||||
865 | } | ||||||||
866 | |||||||||
867 | if (extra_op != NULL((void*)0) && PyArray_Check(extra_op)((((PyObject*)(extra_op))->ob_type) == (&PyArray_Type) || PyType_IsSubtype((((PyObject*)(extra_op))->ob_type), ( &PyArray_Type))) && | ||||||||
868 | solve_may_share_memory(self, (PyArrayObject *)extra_op, 1) != 0) { | ||||||||
869 | return 1; | ||||||||
870 | } | ||||||||
871 | |||||||||
872 | return 0; | ||||||||
873 | } | ||||||||
874 | |||||||||
875 | |||||||||
876 | /** | ||||||||
877 | * Get pointer for an integer index. | ||||||||
878 | * | ||||||||
879 | * For a purely integer index, set ptr to the memory address. | ||||||||
880 | * Returns 0 on success, -1 on failure. | ||||||||
881 | * The caller must ensure that the index is a full integer | ||||||||
882 | * one. | ||||||||
883 | * | ||||||||
884 | * @param Array being indexed | ||||||||
885 | * @param result pointer | ||||||||
886 | * @param parsed index information | ||||||||
887 | * @param number of indices | ||||||||
888 | * | ||||||||
889 | * @return 0 on success -1 on failure | ||||||||
890 | */ | ||||||||
891 | static int | ||||||||
892 | get_item_pointer(PyArrayObject *self, char **ptr, | ||||||||
893 | npy_index_info *indices, int index_num) { | ||||||||
894 | int i; | ||||||||
895 | *ptr = PyArray_BYTES(self); | ||||||||
896 | for (i=0; i < index_num; i++) { | ||||||||
897 | if ((check_and_adjust_index(&(indices[i].value), | ||||||||
898 | PyArray_DIMS(self)[i], i, NULL((void*)0))) < 0) { | ||||||||
899 | return -1; | ||||||||
900 | } | ||||||||
901 | *ptr += PyArray_STRIDE(self, i) * indices[i].value; | ||||||||
902 | } | ||||||||
903 | return 0; | ||||||||
904 | } | ||||||||
905 | |||||||||
906 | |||||||||
907 | /** | ||||||||
908 | * Get view into an array using all non-array indices. | ||||||||
909 | * | ||||||||
910 | * For any index, get a view of the subspace into the original | ||||||||
911 | * array. If there are no fancy indices, this is the result of | ||||||||
912 | * the indexing operation. | ||||||||
913 | * Ensure_array allows to fetch a safe subspace view for advanced | ||||||||
914 | * indexing. | ||||||||
915 | * | ||||||||
916 | * @param Array being indexed | ||||||||
917 | * @param resulting array (new reference) | ||||||||
918 | * @param parsed index information | ||||||||
919 | * @param number of indices | ||||||||
920 | * @param Whether result should inherit the type from self | ||||||||
921 | * | ||||||||
922 | * @return 0 on success -1 on failure | ||||||||
923 | */ | ||||||||
924 | static int | ||||||||
925 | get_view_from_index(PyArrayObject *self, PyArrayObject **view, | ||||||||
926 | npy_index_info *indices, int index_num, int ensure_array) { | ||||||||
927 | npy_intp new_strides[NPY_MAXDIMS32]; | ||||||||
928 | npy_intp new_shape[NPY_MAXDIMS32]; | ||||||||
929 | int i, j; | ||||||||
930 | int new_dim = 0; | ||||||||
931 | int orig_dim = 0; | ||||||||
932 | char *data_ptr = PyArray_BYTES(self); | ||||||||
933 | |||||||||
934 | /* for slice parsing */ | ||||||||
935 | npy_intp start, stop, step, n_steps; | ||||||||
936 | |||||||||
937 | for (i=0; i < index_num; i++) { | ||||||||
938 | switch (indices[i].type) { | ||||||||
939 | case HAS_INTEGER: | ||||||||
940 | if ((check_and_adjust_index(&indices[i].value, | ||||||||
941 | PyArray_DIMS(self)[orig_dim], orig_dim, | ||||||||
942 | NULL((void*)0))) < 0) { | ||||||||
943 | return -1; | ||||||||
944 | } | ||||||||
945 | data_ptr += PyArray_STRIDE(self, orig_dim) * indices[i].value; | ||||||||
946 | |||||||||
947 | new_dim += 0; | ||||||||
948 | orig_dim += 1; | ||||||||
949 | break; | ||||||||
950 | case HAS_ELLIPSIS: | ||||||||
951 | for (j=0; j < indices[i].value; j++) { | ||||||||
952 | new_strides[new_dim] = PyArray_STRIDE(self, orig_dim); | ||||||||
953 | new_shape[new_dim] = PyArray_DIMS(self)[orig_dim]; | ||||||||
954 | new_dim += 1; | ||||||||
955 | orig_dim += 1; | ||||||||
956 | } | ||||||||
957 | break; | ||||||||
958 | case HAS_SLICE: | ||||||||
959 | if (PySlice_GetIndicesEx(indices[i].object,( PySlice_Unpack((indices[i].object), (&start), (&stop ), (&step)) < 0 ? ((*(&n_steps) = 0), -1) : ((*(& n_steps) = PySlice_AdjustIndices((PyArray_DIMS(self)[orig_dim ]), (&start), (&stop), *(&step))), 0)) | ||||||||
960 | PyArray_DIMS(self)[orig_dim],( PySlice_Unpack((indices[i].object), (&start), (&stop ), (&step)) < 0 ? ((*(&n_steps) = 0), -1) : ((*(& n_steps) = PySlice_AdjustIndices((PyArray_DIMS(self)[orig_dim ]), (&start), (&stop), *(&step))), 0)) | ||||||||
961 | &start, &stop, &step, &n_steps)( PySlice_Unpack((indices[i].object), (&start), (&stop ), (&step)) < 0 ? ((*(&n_steps) = 0), -1) : ((*(& n_steps) = PySlice_AdjustIndices((PyArray_DIMS(self)[orig_dim ]), (&start), (&stop), *(&step))), 0)) < 0) { | ||||||||
962 | return -1; | ||||||||
963 | } | ||||||||
964 | if (n_steps <= 0) { | ||||||||
965 | /* TODO: Always points to start then, could change that */ | ||||||||
966 | n_steps = 0; | ||||||||
967 | step = 1; | ||||||||
968 | start = 0; | ||||||||
969 | } | ||||||||
970 | |||||||||
971 | data_ptr += PyArray_STRIDE(self, orig_dim) * start; | ||||||||
972 | new_strides[new_dim] = PyArray_STRIDE(self, orig_dim) * step; | ||||||||
973 | new_shape[new_dim] = n_steps; | ||||||||
974 | new_dim += 1; | ||||||||
975 | orig_dim += 1; | ||||||||
976 | break; | ||||||||
977 | case HAS_NEWAXIS: | ||||||||
978 | new_strides[new_dim] = 0; | ||||||||
979 | new_shape[new_dim] = 1; | ||||||||
980 | new_dim += 1; | ||||||||
981 | break; | ||||||||
982 | /* Fancy and 0-d boolean indices are ignored here */ | ||||||||
983 | case HAS_0D_BOOL: | ||||||||
984 | break; | ||||||||
985 | default: | ||||||||
986 | new_dim += 0; | ||||||||
987 | orig_dim += 1; | ||||||||
988 | break; | ||||||||
989 | } | ||||||||
990 | } | ||||||||
991 | |||||||||
992 | /* Create the new view and set the base array */ | ||||||||
993 | Py_INCREF(PyArray_DESCR(self))_Py_INCREF(((PyObject*)(PyArray_DESCR(self)))); | ||||||||
994 | *view = (PyArrayObject *)PyArray_NewFromDescrAndBase( | ||||||||
995 | ensure_array ? &PyArray_Type : Py_TYPE(self)(((PyObject*)(self))->ob_type), | ||||||||
996 | PyArray_DESCR(self), | ||||||||
997 | new_dim, new_shape, new_strides, data_ptr, | ||||||||
998 | PyArray_FLAGS(self), | ||||||||
999 | ensure_array ? NULL((void*)0) : (PyObject *)self, | ||||||||
1000 | (PyObject *)self); | ||||||||
1001 | if (*view == NULL((void*)0)) { | ||||||||
1002 | return -1; | ||||||||
1003 | } | ||||||||
1004 | |||||||||
1005 | return 0; | ||||||||
1006 | } | ||||||||
1007 | |||||||||
1008 | |||||||||
1009 | /* | ||||||||
1010 | * Implements boolean indexing. This produces a one-dimensional | ||||||||
1011 | * array which picks out all of the elements of 'self' for which | ||||||||
1012 | * the corresponding element of 'op' is True. | ||||||||
1013 | * | ||||||||
1014 | * This operation is somewhat unfortunate, because to produce | ||||||||
1015 | * a one-dimensional output array, it has to choose a particular | ||||||||
1016 | * iteration order, in the case of NumPy that is always C order even | ||||||||
1017 | * though this function allows different choices. | ||||||||
1018 | */ | ||||||||
1019 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArrayObject * | ||||||||
1020 | array_boolean_subscript(PyArrayObject *self, | ||||||||
1021 | PyArrayObject *bmask, NPY_ORDER order) | ||||||||
1022 | { | ||||||||
1023 | npy_intp size, itemsize; | ||||||||
1024 | char *ret_data; | ||||||||
1025 | PyArray_Descr *dtype; | ||||||||
1026 | PyArrayObject *ret; | ||||||||
1027 | int needs_api = 0; | ||||||||
1028 | |||||||||
1029 | size = count_boolean_trues(PyArray_NDIM(bmask), PyArray_DATA(bmask), | ||||||||
1030 | PyArray_DIMS(bmask), PyArray_STRIDES(bmask)); | ||||||||
1031 | |||||||||
1032 | /* Allocate the output of the boolean indexing */ | ||||||||
1033 | dtype = PyArray_DESCR(self); | ||||||||
1034 | Py_INCREF(dtype)_Py_INCREF(((PyObject*)(dtype))); | ||||||||
1035 | ret = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, dtype, 1, &size, | ||||||||
1036 | NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)); | ||||||||
1037 | if (ret == NULL((void*)0)) { | ||||||||
1038 | return NULL((void*)0); | ||||||||
1039 | } | ||||||||
1040 | |||||||||
1041 | itemsize = dtype->elsize; | ||||||||
1042 | ret_data = PyArray_DATA(ret); | ||||||||
1043 | |||||||||
1044 | /* Create an iterator for the data */ | ||||||||
1045 | if (size > 0) { | ||||||||
1046 | NpyIter *iter; | ||||||||
1047 | PyArrayObject *op[2] = {self, bmask}; | ||||||||
1048 | npy_uint32 flags, op_flags[2]; | ||||||||
1049 | npy_intp fixed_strides[3]; | ||||||||
1050 | |||||||||
1051 | NpyIter_IterNextFunc *iternext; | ||||||||
1052 | npy_intp innersize, *innerstrides; | ||||||||
1053 | char **dataptrs; | ||||||||
1054 | |||||||||
1055 | npy_intp self_stride, bmask_stride, subloopsize; | ||||||||
1056 | char *self_data; | ||||||||
1057 | char *bmask_data; | ||||||||
1058 | NPY_BEGIN_THREADS_DEFPyThreadState *_save=((void*)0);; | ||||||||
1059 | |||||||||
1060 | /* Set up the iterator */ | ||||||||
1061 | flags = NPY_ITER_EXTERNAL_LOOP0x00000008 | NPY_ITER_REFS_OK0x00000020; | ||||||||
1062 | op_flags[0] = NPY_ITER_READONLY0x00020000 | NPY_ITER_NO_BROADCAST0x08000000; | ||||||||
1063 | op_flags[1] = NPY_ITER_READONLY0x00020000; | ||||||||
1064 | |||||||||
1065 | iter = NpyIter_MultiNew(2, op, flags, order, NPY_NO_CASTING, | ||||||||
1066 | op_flags, NULL((void*)0)); | ||||||||
1067 | if (iter == NULL((void*)0)) { | ||||||||
1068 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||
1069 | return NULL((void*)0); | ||||||||
1070 | } | ||||||||
1071 | |||||||||
1072 | /* Get a dtype transfer function */ | ||||||||
1073 | NpyIter_GetInnerFixedStrideArray(iter, fixed_strides); | ||||||||
1074 | NPY_cast_info cast_info; | ||||||||
1075 | if (PyArray_GetDTypeTransferFunction( | ||||||||
1076 | IsUintAligned(self) && IsAligned(self), | ||||||||
1077 | fixed_strides[0], itemsize, | ||||||||
1078 | dtype, dtype, | ||||||||
1079 | 0, | ||||||||
1080 | &cast_info, | ||||||||
1081 | &needs_api) != NPY_SUCCEED1) { | ||||||||
1082 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||
1083 | NpyIter_Deallocate(iter); | ||||||||
1084 | return NULL((void*)0); | ||||||||
1085 | } | ||||||||
1086 | |||||||||
1087 | /* Get the values needed for the inner loop */ | ||||||||
1088 | iternext = NpyIter_GetIterNext(iter, NULL((void*)0)); | ||||||||
1089 | if (iternext == NULL((void*)0)) { | ||||||||
1090 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||
1091 | NpyIter_Deallocate(iter); | ||||||||
1092 | NPY_cast_info_xfree(&cast_info); | ||||||||
1093 | return NULL((void*)0); | ||||||||
1094 | } | ||||||||
1095 | |||||||||
1096 | NPY_BEGIN_THREADS_NDITER(iter)do { if (!NpyIter_IterationNeedsAPI(iter)) { do { if ((NpyIter_GetIterSize (iter)) > 500) { _save = PyEval_SaveThread();} } while (0) ;; } } while(0); | ||||||||
1097 | |||||||||
1098 | innerstrides = NpyIter_GetInnerStrideArray(iter); | ||||||||
1099 | dataptrs = NpyIter_GetDataPtrArray(iter); | ||||||||
1100 | |||||||||
1101 | self_stride = innerstrides[0]; | ||||||||
1102 | bmask_stride = innerstrides[1]; | ||||||||
1103 | npy_intp strides[2] = {self_stride, itemsize}; | ||||||||
1104 | |||||||||
1105 | int res = 0; | ||||||||
1106 | do { | ||||||||
1107 | innersize = *NpyIter_GetInnerLoopSizePtr(iter); | ||||||||
1108 | self_data = dataptrs[0]; | ||||||||
1109 | bmask_data = dataptrs[1]; | ||||||||
1110 | |||||||||
1111 | while (innersize > 0) { | ||||||||
1112 | /* Skip masked values */ | ||||||||
1113 | bmask_data = npy_memchr(bmask_data, 0, bmask_stride, | ||||||||
1114 | innersize, &subloopsize, 1); | ||||||||
1115 | innersize -= subloopsize; | ||||||||
1116 | self_data += subloopsize * self_stride; | ||||||||
1117 | /* Process unmasked values */ | ||||||||
1118 | bmask_data = npy_memchr(bmask_data, 0, bmask_stride, innersize, | ||||||||
1119 | &subloopsize, 0); | ||||||||
1120 | char *args[2] = {self_data, ret_data}; | ||||||||
1121 | res = cast_info.func(&cast_info.context, | ||||||||
1122 | args, &subloopsize, strides, cast_info.auxdata); | ||||||||
1123 | if (res < 0) { | ||||||||
1124 | break; | ||||||||
1125 | } | ||||||||
1126 | innersize -= subloopsize; | ||||||||
1127 | self_data += subloopsize * self_stride; | ||||||||
1128 | ret_data += subloopsize * itemsize; | ||||||||
1129 | } | ||||||||
1130 | } while (iternext(iter)); | ||||||||
1131 | |||||||||
1132 | NPY_END_THREADSdo { if (_save) { PyEval_RestoreThread(_save); _save = ((void *)0);} } while (0);; | ||||||||
1133 | |||||||||
1134 | if (!NpyIter_Deallocate(iter)) { | ||||||||
1135 | res = -1; | ||||||||
1136 | } | ||||||||
1137 | NPY_cast_info_xfree(&cast_info); | ||||||||
1138 | if (res < 0) { | ||||||||
1139 | /* Should be practically impossible, since there is no cast */ | ||||||||
1140 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||
1141 | return NULL((void*)0); | ||||||||
1142 | } | ||||||||
1143 | } | ||||||||
1144 | |||||||||
1145 | if (!PyArray_CheckExact(self)(((PyObject*)(self))->ob_type == &PyArray_Type)) { | ||||||||
1146 | PyArrayObject *tmp = ret; | ||||||||
1147 | |||||||||
1148 | Py_INCREF(dtype)_Py_INCREF(((PyObject*)(dtype))); | ||||||||
1149 | ret = (PyArrayObject *)PyArray_NewFromDescrAndBase( | ||||||||
1150 | Py_TYPE(self)(((PyObject*)(self))->ob_type), dtype, | ||||||||
1151 | 1, &size, PyArray_STRIDES(ret), PyArray_BYTES(ret), | ||||||||
1152 | PyArray_FLAGS(self), (PyObject *)self, (PyObject *)tmp); | ||||||||
1153 | |||||||||
1154 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | ||||||||
1155 | if (ret == NULL((void*)0)) { | ||||||||
1156 | return NULL((void*)0); | ||||||||
1157 | } | ||||||||
1158 | } | ||||||||
1159 | |||||||||
1160 | return ret; | ||||||||
1161 | } | ||||||||
1162 | |||||||||
1163 | /* | ||||||||
1164 | * Implements boolean indexing assignment. This takes the one-dimensional | ||||||||
1165 | * array 'v' and assigns its values to all of the elements of 'self' for which | ||||||||
1166 | * the corresponding element of 'op' is True. | ||||||||
1167 | * | ||||||||
1168 | * This operation is somewhat unfortunate, because to match up with | ||||||||
1169 | * a one-dimensional output array, it has to choose a particular | ||||||||
1170 | * iteration order, in the case of NumPy that is always C order even | ||||||||
1171 | * though this function allows different choices. | ||||||||
1172 | * | ||||||||
1173 | * Returns 0 on success, -1 on failure. | ||||||||
1174 | */ | ||||||||
1175 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||
1176 | array_assign_boolean_subscript(PyArrayObject *self, | ||||||||
1177 | PyArrayObject *bmask, PyArrayObject *v, NPY_ORDER order) | ||||||||
1178 | { | ||||||||
1179 | npy_intp size, v_stride; | ||||||||
1180 | char *v_data; | ||||||||
1181 | int needs_api = 0; | ||||||||
1182 | npy_intp bmask_size; | ||||||||
1183 | |||||||||
1184 | if (PyArray_DESCR(bmask)->type_num != NPY_BOOL) { | ||||||||
1185 | PyErr_SetString(PyExc_TypeError, | ||||||||
1186 | "NumPy boolean array indexing assignment " | ||||||||
1187 | "requires a boolean index"); | ||||||||
1188 | return -1; | ||||||||
1189 | } | ||||||||
1190 | |||||||||
1191 | if (PyArray_NDIM(v) > 1) { | ||||||||
1192 | PyErr_Format(PyExc_TypeError, | ||||||||
1193 | "NumPy boolean array indexing assignment " | ||||||||
1194 | "requires a 0 or 1-dimensional input, input " | ||||||||
1195 | "has %d dimensions", PyArray_NDIM(v)); | ||||||||
1196 | return -1; | ||||||||
1197 | } | ||||||||
1198 | |||||||||
1199 | if (PyArray_NDIM(bmask) != PyArray_NDIM(self)) { | ||||||||
1200 | PyErr_SetString(PyExc_ValueError, | ||||||||
1201 | "The boolean mask assignment indexing array " | ||||||||
1202 | "must have the same number of dimensions as " | ||||||||
1203 | "the array being indexed"); | ||||||||
1204 | return -1; | ||||||||
1205 | } | ||||||||
1206 | |||||||||
1207 | size = count_boolean_trues(PyArray_NDIM(bmask), PyArray_DATA(bmask), | ||||||||
1208 | PyArray_DIMS(bmask), PyArray_STRIDES(bmask)); | ||||||||
1209 | /* Correction factor for broadcasting 'bmask' to 'self' */ | ||||||||
1210 | bmask_size = PyArray_SIZE(bmask)PyArray_MultiplyList(PyArray_DIMS(bmask), PyArray_NDIM(bmask) ); | ||||||||
1211 | if (bmask_size > 0) { | ||||||||
1212 | size *= PyArray_SIZE(self)PyArray_MultiplyList(PyArray_DIMS(self), PyArray_NDIM(self)) / bmask_size; | ||||||||
1213 | } | ||||||||
1214 | |||||||||
1215 | /* Tweak the strides for 0-dim and broadcasting cases */ | ||||||||
1216 | if (PyArray_NDIM(v) > 0 && PyArray_DIMS(v)[0] != 1) { | ||||||||
1217 | if (size != PyArray_DIMS(v)[0]) { | ||||||||
1218 | PyErr_Format(PyExc_ValueError, | ||||||||
1219 | "NumPy boolean array indexing assignment " | ||||||||
1220 | "cannot assign %" NPY_INTP_FMT"ld" " input values to " | ||||||||
1221 | "the %" NPY_INTP_FMT"ld" " output values where the mask is true", | ||||||||
1222 | PyArray_DIMS(v)[0], size); | ||||||||
1223 | return -1; | ||||||||
1224 | } | ||||||||
1225 | v_stride = PyArray_STRIDES(v)[0]; | ||||||||
1226 | } | ||||||||
1227 | else { | ||||||||
1228 | v_stride = 0; | ||||||||
1229 | } | ||||||||
1230 | |||||||||
1231 | v_data = PyArray_DATA(v); | ||||||||
1232 | |||||||||
1233 | /* Create an iterator for the data */ | ||||||||
1234 | int res = 0; | ||||||||
1235 | if (size > 0) { | ||||||||
1236 | NpyIter *iter; | ||||||||
1237 | PyArrayObject *op[2] = {self, bmask}; | ||||||||
1238 | npy_uint32 flags, op_flags[2]; | ||||||||
1239 | npy_intp fixed_strides[3]; | ||||||||
1240 | |||||||||
1241 | NpyIter_IterNextFunc *iternext; | ||||||||
1242 | npy_intp innersize, *innerstrides; | ||||||||
1243 | char **dataptrs; | ||||||||
1244 | |||||||||
1245 | npy_intp self_stride, bmask_stride, subloopsize; | ||||||||
1246 | char *self_data; | ||||||||
1247 | char *bmask_data; | ||||||||
1248 | NPY_BEGIN_THREADS_DEFPyThreadState *_save=((void*)0);; | ||||||||
1249 | |||||||||
1250 | /* Set up the iterator */ | ||||||||
1251 | flags = NPY_ITER_EXTERNAL_LOOP0x00000008 | NPY_ITER_REFS_OK0x00000020; | ||||||||
1252 | op_flags[0] = NPY_ITER_WRITEONLY0x00040000 | NPY_ITER_NO_BROADCAST0x08000000; | ||||||||
1253 | op_flags[1] = NPY_ITER_READONLY0x00020000; | ||||||||
1254 | |||||||||
1255 | iter = NpyIter_MultiNew(2, op, flags, order, NPY_NO_CASTING, | ||||||||
1256 | op_flags, NULL((void*)0)); | ||||||||
1257 | if (iter == NULL((void*)0)) { | ||||||||
1258 | return -1; | ||||||||
1259 | } | ||||||||
1260 | |||||||||
1261 | /* Get the values needed for the inner loop */ | ||||||||
1262 | iternext = NpyIter_GetIterNext(iter, NULL((void*)0)); | ||||||||
1263 | if (iternext == NULL((void*)0)) { | ||||||||
1264 | NpyIter_Deallocate(iter); | ||||||||
1265 | return -1; | ||||||||
1266 | } | ||||||||
1267 | |||||||||
1268 | innerstrides = NpyIter_GetInnerStrideArray(iter); | ||||||||
1269 | dataptrs = NpyIter_GetDataPtrArray(iter); | ||||||||
1270 | |||||||||
1271 | self_stride = innerstrides[0]; | ||||||||
1272 | bmask_stride = innerstrides[1]; | ||||||||
1273 | |||||||||
1274 | /* Get a dtype transfer function */ | ||||||||
1275 | NpyIter_GetInnerFixedStrideArray(iter, fixed_strides); | ||||||||
1276 | NPY_cast_info cast_info; | ||||||||
1277 | if (PyArray_GetDTypeTransferFunction( | ||||||||
1278 | IsUintAligned(self) && IsAligned(self) && | ||||||||
1279 | IsUintAligned(v) && IsAligned(v), | ||||||||
1280 | v_stride, fixed_strides[0], | ||||||||
1281 | PyArray_DESCR(v), PyArray_DESCR(self), | ||||||||
1282 | 0, | ||||||||
1283 | &cast_info, | ||||||||
1284 | &needs_api) != NPY_SUCCEED1) { | ||||||||
1285 | NpyIter_Deallocate(iter); | ||||||||
1286 | return -1; | ||||||||
1287 | } | ||||||||
1288 | |||||||||
1289 | if (!needs_api) { | ||||||||
1290 | NPY_BEGIN_THREADS_NDITER(iter)do { if (!NpyIter_IterationNeedsAPI(iter)) { do { if ((NpyIter_GetIterSize (iter)) > 500) { _save = PyEval_SaveThread();} } while (0) ;; } } while(0); | ||||||||
1291 | } | ||||||||
1292 | |||||||||
1293 | npy_intp strides[2] = {v_stride, self_stride}; | ||||||||
1294 | |||||||||
1295 | do { | ||||||||
1296 | innersize = *NpyIter_GetInnerLoopSizePtr(iter); | ||||||||
1297 | self_data = dataptrs[0]; | ||||||||
1298 | bmask_data = dataptrs[1]; | ||||||||
1299 | |||||||||
1300 | while (innersize > 0) { | ||||||||
1301 | /* Skip masked values */ | ||||||||
1302 | bmask_data = npy_memchr(bmask_data, 0, bmask_stride, | ||||||||
1303 | innersize, &subloopsize, 1); | ||||||||
1304 | innersize -= subloopsize; | ||||||||
1305 | self_data += subloopsize * self_stride; | ||||||||
1306 | /* Process unmasked values */ | ||||||||
1307 | bmask_data = npy_memchr(bmask_data, 0, bmask_stride, innersize, | ||||||||
1308 | &subloopsize, 0); | ||||||||
1309 | |||||||||
1310 | char *args[2] = {v_data, self_data}; | ||||||||
1311 | res = cast_info.func(&cast_info.context, | ||||||||
1312 | args, &subloopsize, strides, cast_info.auxdata); | ||||||||
1313 | if (res < 0) { | ||||||||
1314 | break; | ||||||||
1315 | } | ||||||||
1316 | innersize -= subloopsize; | ||||||||
1317 | self_data += subloopsize * self_stride; | ||||||||
1318 | v_data += subloopsize * v_stride; | ||||||||
1319 | } | ||||||||
1320 | } while (iternext(iter)); | ||||||||
1321 | |||||||||
1322 | if (!needs_api) { | ||||||||
1323 | NPY_END_THREADSdo { if (_save) { PyEval_RestoreThread(_save); _save = ((void *)0);} } while (0);; | ||||||||
1324 | } | ||||||||
1325 | |||||||||
1326 | NPY_cast_info_xfree(&cast_info); | ||||||||
1327 | if (!NpyIter_Deallocate(iter)) { | ||||||||
1328 | res = -1; | ||||||||
1329 | } | ||||||||
1330 | } | ||||||||
1331 | |||||||||
1332 | return res; | ||||||||
1333 | } | ||||||||
1334 | |||||||||
1335 | |||||||||
1336 | /* | ||||||||
1337 | * C-level integer indexing always returning an array and never a scalar. | ||||||||
1338 | * Works also for subclasses, but it will not be called on one from the | ||||||||
1339 | * Python API. | ||||||||
1340 | * | ||||||||
1341 | * This function does not accept negative indices because it is called by | ||||||||
1342 | * PySequence_GetItem (through array_item) and that converts them to | ||||||||
1343 | * positive indices. | ||||||||
1344 | */ | ||||||||
1345 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||
1346 | array_item_asarray(PyArrayObject *self, npy_intp i) | ||||||||
1347 | { | ||||||||
1348 | npy_index_info indices[2]; | ||||||||
1349 | PyObject *result; | ||||||||
1350 | |||||||||
1351 | if (PyArray_NDIM(self) == 0) { | ||||||||
1352 | PyErr_SetString(PyExc_IndexError, | ||||||||
1353 | "too many indices for array"); | ||||||||
1354 | return NULL((void*)0); | ||||||||
1355 | } | ||||||||
1356 | if (i < 0) { | ||||||||
1357 | /* This is an error, but undo PySequence_GetItem fix for message */ | ||||||||
1358 | i -= PyArray_DIM(self, 0); | ||||||||
1359 | } | ||||||||
1360 | |||||||||
1361 | indices[0].value = i; | ||||||||
1362 | indices[0].type = HAS_INTEGER; | ||||||||
1363 | indices[1].value = PyArray_NDIM(self) - 1; | ||||||||
1364 | indices[1].type = HAS_ELLIPSIS; | ||||||||
1365 | if (get_view_from_index(self, (PyArrayObject **)&result, | ||||||||
1366 | indices, 2, 0) < 0) { | ||||||||
1367 | return NULL((void*)0); | ||||||||
1368 | } | ||||||||
1369 | return result; | ||||||||
1370 | } | ||||||||
1371 | |||||||||
1372 | |||||||||
1373 | /* | ||||||||
1374 | * Python C-Api level item subscription (implementation for PySequence_GetItem) | ||||||||
1375 | * | ||||||||
1376 | * Negative indices are not accepted because PySequence_GetItem converts | ||||||||
1377 | * them to positive indices before calling this. | ||||||||
1378 | */ | ||||||||
1379 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||
1380 | array_item(PyArrayObject *self, Py_ssize_t i) | ||||||||
1381 | { | ||||||||
1382 | if (PyArray_NDIM(self) == 1) { | ||||||||
1383 | char *item; | ||||||||
1384 | npy_index_info index; | ||||||||
1385 | |||||||||
1386 | if (i < 0) { | ||||||||
1387 | /* This is an error, but undo PySequence_GetItem fix for message */ | ||||||||
1388 | i -= PyArray_DIM(self, 0); | ||||||||
1389 | } | ||||||||
1390 | |||||||||
1391 | index.value = i; | ||||||||
1392 | index.type = HAS_INTEGER; | ||||||||
1393 | if (get_item_pointer(self, &item, &index, 1) < 0) { | ||||||||
1394 | return NULL((void*)0); | ||||||||
1395 | } | ||||||||
1396 | return PyArray_Scalar(item, PyArray_DESCR(self), (PyObject *)self); | ||||||||
1397 | } | ||||||||
1398 | else { | ||||||||
1399 | return array_item_asarray(self, i); | ||||||||
1400 | } | ||||||||
1401 | } | ||||||||
1402 | |||||||||
1403 | |||||||||
1404 | /* make sure subscript always returns an array object */ | ||||||||
1405 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||
1406 | array_subscript_asarray(PyArrayObject *self, PyObject *op) | ||||||||
1407 | { | ||||||||
1408 | return PyArray_EnsureAnyArray(array_subscript(self, op)); | ||||||||
1409 | } | ||||||||
1410 | |||||||||
1411 | /* | ||||||||
1412 | * Attempts to subscript an array using a field name or list of field names. | ||||||||
1413 | * | ||||||||
1414 | * ret = 0, view != NULL: view points to the requested fields of arr | ||||||||
1415 | * ret = 0, view == NULL: an error occurred | ||||||||
1416 | * ret = -1, view == NULL: unrecognized input, this is not a field index. | ||||||||
1417 | */ | ||||||||
1418 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||
1419 | _get_field_view(PyArrayObject *arr, PyObject *ind, PyArrayObject **view) | ||||||||
1420 | { | ||||||||
1421 | *view = NULL((void*)0); | ||||||||
1422 | |||||||||
1423 | /* first check for a single field name */ | ||||||||
1424 | if (PyUnicode_Check(ind)((((((PyObject*)(ind))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | ||||||||
1425 | PyObject *tup; | ||||||||
1426 | PyArray_Descr *fieldtype; | ||||||||
1427 | npy_intp offset; | ||||||||
1428 | |||||||||
1429 | /* get the field offset and dtype */ | ||||||||
1430 | tup = PyDict_GetItemWithError(PyArray_DESCR(arr)->fields, ind); | ||||||||
1431 | if (tup == NULL((void*)0) && PyErr_Occurred()) { | ||||||||
1432 | return 0; | ||||||||
1433 | } | ||||||||
1434 | else if (tup == NULL((void*)0)){ | ||||||||
1435 | PyErr_Format(PyExc_ValueError, "no field of name %S", ind); | ||||||||
1436 | return 0; | ||||||||
1437 | } | ||||||||
1438 | if (_unpack_field(tup, &fieldtype, &offset) < 0) { | ||||||||
1439 | return 0; | ||||||||
1440 | } | ||||||||
1441 | |||||||||
1442 | /* view the array at the new offset+dtype */ | ||||||||
1443 | Py_INCREF(fieldtype)_Py_INCREF(((PyObject*)(fieldtype))); | ||||||||
1444 | *view = (PyArrayObject*)PyArray_NewFromDescr_int( | ||||||||
1445 | Py_TYPE(arr)(((PyObject*)(arr))->ob_type), | ||||||||
1446 | fieldtype, | ||||||||
1447 | PyArray_NDIM(arr), | ||||||||
1448 | PyArray_SHAPE(arr), | ||||||||
1449 | PyArray_STRIDES(arr), | ||||||||
1450 | PyArray_BYTES(arr) + offset, | ||||||||
1451 | PyArray_FLAGS(arr), | ||||||||
1452 | (PyObject *)arr, (PyObject *)arr, | ||||||||
1453 | 0, 1); | ||||||||
1454 | if (*view == NULL((void*)0)) { | ||||||||
1455 | return 0; | ||||||||
1456 | } | ||||||||
1457 | return 0; | ||||||||
1458 | } | ||||||||
1459 | |||||||||
1460 | /* next check for a list of field names */ | ||||||||
1461 | else if (PySequence_Check(ind) && !PyTuple_Check(ind)((((((PyObject*)(ind))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | ||||||||
1462 | npy_intp seqlen, i; | ||||||||
1463 | PyArray_Descr *view_dtype; | ||||||||
1464 | |||||||||
1465 | seqlen = PySequence_Size(ind); | ||||||||
1466 | |||||||||
1467 | /* quit if have a fake sequence-like, which errors on len()*/ | ||||||||
1468 | if (seqlen == -1) { | ||||||||
1469 | PyErr_Clear(); | ||||||||
1470 | return -1; | ||||||||
1471 | } | ||||||||
1472 | /* 0-len list is handled elsewhere as an integer index */ | ||||||||
1473 | if (seqlen == 0) { | ||||||||
1474 | return -1; | ||||||||
1475 | } | ||||||||
1476 | |||||||||
1477 | /* check the items are strings */ | ||||||||
1478 | for (i = 0; i < seqlen; i++) { | ||||||||
1479 | npy_bool is_string; | ||||||||
1480 | PyObject *item = PySequence_GetItem(ind, i); | ||||||||
1481 | if (item == NULL((void*)0)) { | ||||||||
1482 | PyErr_Clear(); | ||||||||
1483 | return -1; | ||||||||
1484 | } | ||||||||
1485 | is_string = PyUnicode_Check(item)((((((PyObject*)(item))->ob_type))->tp_flags & ((1UL << 28))) != 0); | ||||||||
1486 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | ||||||||
1487 | if (!is_string) { | ||||||||
1488 | return -1; | ||||||||
1489 | } | ||||||||
1490 | } | ||||||||
1491 | |||||||||
1492 | /* Call into the dtype subscript */ | ||||||||
1493 | view_dtype = arraydescr_field_subset_view(PyArray_DESCR(arr), ind); | ||||||||
1494 | if (view_dtype == NULL((void*)0)) { | ||||||||
1495 | return 0; | ||||||||
1496 | } | ||||||||
1497 | |||||||||
1498 | *view = (PyArrayObject*)PyArray_NewFromDescr_int( | ||||||||
1499 | Py_TYPE(arr)(((PyObject*)(arr))->ob_type), | ||||||||
1500 | view_dtype, | ||||||||
1501 | PyArray_NDIM(arr), | ||||||||
1502 | PyArray_SHAPE(arr), | ||||||||
1503 | PyArray_STRIDES(arr), | ||||||||
1504 | PyArray_DATA(arr), | ||||||||
1505 | PyArray_FLAGS(arr), | ||||||||
1506 | (PyObject *)arr, (PyObject *)arr, | ||||||||
1507 | 0, 1); | ||||||||
1508 | |||||||||
1509 | if (*view == NULL((void*)0)) { | ||||||||
1510 | return 0; | ||||||||
1511 | } | ||||||||
1512 | |||||||||
1513 | return 0; | ||||||||
1514 | } | ||||||||
1515 | return -1; | ||||||||
1516 | } | ||||||||
1517 | |||||||||
1518 | /* | ||||||||
1519 | * General function for indexing a NumPy array with a Python object. | ||||||||
1520 | */ | ||||||||
1521 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||
1522 | array_subscript(PyArrayObject *self, PyObject *op) | ||||||||
1523 | { | ||||||||
1524 | int index_type; | ||||||||
1525 | int index_num; | ||||||||
1526 | int i, ndim, fancy_ndim; | ||||||||
1527 | /* | ||||||||
1528 | * Index info array. We can have twice as many indices as dimensions | ||||||||
1529 | * (because of None). The + 1 is to not need to check as much. | ||||||||
1530 | */ | ||||||||
1531 | npy_index_info indices[NPY_MAXDIMS32 * 2 + 1]; | ||||||||
1532 | |||||||||
1533 | PyArrayObject *view = NULL((void*)0); | ||||||||
1534 | PyObject *result = NULL((void*)0); | ||||||||
1535 | |||||||||
1536 | PyArrayMapIterObject * mit = NULL((void*)0); | ||||||||
1537 | |||||||||
1538 | /* return fields if op is a string index */ | ||||||||
1539 | if (PyDataType_HASFIELDS(PyArray_DESCR(self))(((PyArray_Descr *)(PyArray_DESCR(self)))->names != ((void *)0))) { | ||||||||
1540 | PyArrayObject *view; | ||||||||
1541 | int ret = _get_field_view(self, op, &view); | ||||||||
1542 | if (ret == 0){ | ||||||||
1543 | if (view == NULL((void*)0)) { | ||||||||
1544 | return NULL((void*)0); | ||||||||
1545 | } | ||||||||
1546 | return (PyObject*)view; | ||||||||
1547 | } | ||||||||
1548 | } | ||||||||
1549 | |||||||||
1550 | /* Prepare the indices */ | ||||||||
1551 | index_type = prepare_index(self, op, indices, &index_num, | ||||||||
1552 | &ndim, &fancy_ndim, 1); | ||||||||
1553 | |||||||||
1554 | if (index_type < 0) { | ||||||||
1555 | return NULL((void*)0); | ||||||||
1556 | } | ||||||||
1557 | |||||||||
1558 | /* Full integer index */ | ||||||||
1559 | else if (index_type == HAS_INTEGER) { | ||||||||
1560 | char *item; | ||||||||
1561 | if (get_item_pointer(self, &item, indices, index_num) < 0) { | ||||||||
1562 | goto finish; | ||||||||
1563 | } | ||||||||
1564 | result = (PyObject *) PyArray_Scalar(item, PyArray_DESCR(self), | ||||||||
1565 | (PyObject *)self); | ||||||||
1566 | /* Because the index is full integer, we do not need to decref */ | ||||||||
1567 | return result; | ||||||||
1568 | } | ||||||||
1569 | |||||||||
1570 | /* Single boolean array */ | ||||||||
1571 | else if (index_type == HAS_BOOL) { | ||||||||
1572 | result = (PyObject *)array_boolean_subscript(self, | ||||||||
1573 | (PyArrayObject *)indices[0].object, | ||||||||
1574 | NPY_CORDER); | ||||||||
1575 | goto finish; | ||||||||
1576 | } | ||||||||
1577 | |||||||||
1578 | /* If it is only a single ellipsis, just return a view */ | ||||||||
1579 | else if (index_type == HAS_ELLIPSIS) { | ||||||||
1580 | /* | ||||||||
1581 | * TODO: Should this be a view or not? The only reason not would be | ||||||||
1582 | * optimization (i.e. of array[...] += 1) I think. | ||||||||
1583 | * Before, it was just self for a single ellipsis. | ||||||||
1584 | */ | ||||||||
1585 | result = PyArray_View(self, NULL((void*)0), NULL((void*)0)); | ||||||||
1586 | /* A single ellipsis, so no need to decref */ | ||||||||
1587 | return result; | ||||||||
1588 | } | ||||||||
1589 | |||||||||
1590 | /* | ||||||||
1591 | * View based indexing. | ||||||||
1592 | * There are two cases here. First we need to create a simple view, | ||||||||
1593 | * second we need to create a (possibly invalid) view for the | ||||||||
1594 | * subspace to the fancy index. This procedure is identical. | ||||||||
1595 | */ | ||||||||
1596 | |||||||||
1597 | else if (index_type & (HAS_SLICE | HAS_NEWAXIS | | ||||||||
1598 | HAS_ELLIPSIS | HAS_INTEGER)) { | ||||||||
1599 | if (get_view_from_index(self, &view, indices, index_num, | ||||||||
1600 | (index_type & HAS_FANCY)) < 0) { | ||||||||
1601 | goto finish; | ||||||||
1602 | } | ||||||||
1603 | |||||||||
1604 | /* | ||||||||
1605 | * There is a scalar array, so we need to force a copy to simulate | ||||||||
1606 | * fancy indexing. | ||||||||
1607 | */ | ||||||||
1608 | if (index_type & HAS_SCALAR_ARRAY) { | ||||||||
1609 | result = PyArray_NewCopy(view, NPY_KEEPORDER); | ||||||||
1610 | goto finish; | ||||||||
1611 | } | ||||||||
1612 | } | ||||||||
1613 | |||||||||
1614 | /* If there is no fancy indexing, we have the result */ | ||||||||
1615 | if (!(index_type & HAS_FANCY)) { | ||||||||
1616 | result = (PyObject *)view; | ||||||||
1617 | Py_INCREF(result)_Py_INCREF(((PyObject*)(result))); | ||||||||
1618 | goto finish; | ||||||||
1619 | } | ||||||||
1620 | |||||||||
1621 | /* | ||||||||
1622 | * Special case for very simple 1-d fancy indexing, which however | ||||||||
1623 | * is quite common. This saves not only a lot of setup time in the | ||||||||
1624 | * iterator, but also is faster (must be exactly fancy because | ||||||||
1625 | * we don't support 0-d booleans here) | ||||||||
1626 | */ | ||||||||
1627 | if (index_type == HAS_FANCY && index_num == 1) { | ||||||||
1628 | /* The array being indexed has one dimension and it is a fancy index */ | ||||||||
1629 | PyArrayObject *ind = (PyArrayObject*)indices[0].object; | ||||||||
1630 | |||||||||
1631 | /* Check if the index is simple enough */ | ||||||||
1632 | if (PyArray_TRIVIALLY_ITERABLE(ind)( PyArray_NDIM(ind) <= 1 || PyArray_CHKFLAGS(ind, 0x0001) || PyArray_CHKFLAGS(ind, 0x0002) ) && | ||||||||
1633 | /* Check if the type is equivalent to INTP */ | ||||||||
1634 | PyArray_ITEMSIZE(ind) == sizeof(npy_intp) && | ||||||||
1635 | PyArray_DESCR(ind)->kind == 'i' && | ||||||||
1636 | IsUintAligned(ind) && | ||||||||
1637 | PyDataType_ISNOTSWAPPED(PyArray_DESCR(ind))((((PyArray_Descr *)(PyArray_DESCR(ind)))->byteorder) != '>' )) { | ||||||||
1638 | |||||||||
1639 | Py_INCREF(PyArray_DESCR(self))_Py_INCREF(((PyObject*)(PyArray_DESCR(self)))); | ||||||||
1640 | result = PyArray_NewFromDescr(&PyArray_Type, | ||||||||
1641 | PyArray_DESCR(self), | ||||||||
1642 | PyArray_NDIM(ind), | ||||||||
1643 | PyArray_SHAPE(ind), | ||||||||
1644 | NULL((void*)0), NULL((void*)0), | ||||||||
1645 | /* Same order as indices */ | ||||||||
1646 | PyArray_ISFORTRAN(ind)(PyArray_CHKFLAGS(ind, 0x0002) && (!PyArray_CHKFLAGS( ind, 0x0001))) ? | ||||||||
1647 | NPY_ARRAY_F_CONTIGUOUS0x0002 : 0, | ||||||||
1648 | NULL((void*)0)); | ||||||||
1649 | if (result == NULL((void*)0)) { | ||||||||
1650 | goto finish; | ||||||||
1651 | } | ||||||||
1652 | |||||||||
1653 | if (mapiter_trivial_get(self, ind, (PyArrayObject *)result) < 0) { | ||||||||
1654 | Py_DECREF(result)_Py_DECREF(((PyObject*)(result))); | ||||||||
1655 | result = NULL((void*)0); | ||||||||
1656 | goto finish; | ||||||||
1657 | } | ||||||||
1658 | |||||||||
1659 | goto wrap_out_array; | ||||||||
1660 | } | ||||||||
1661 | } | ||||||||
1662 | |||||||||
1663 | /* fancy indexing has to be used. And view is the subspace. */ | ||||||||
1664 | mit = (PyArrayMapIterObject *)PyArray_MapIterNew(indices, index_num, | ||||||||
1665 | index_type, | ||||||||
1666 | ndim, fancy_ndim, | ||||||||
1667 | self, view, 0, | ||||||||
1668 | NPY_ITER_READONLY0x00020000, | ||||||||
1669 | NPY_ITER_WRITEONLY0x00040000, | ||||||||
1670 | NULL((void*)0), PyArray_DESCR(self)); | ||||||||
1671 | if (mit == NULL((void*)0)) { | ||||||||
1672 | goto finish; | ||||||||
1673 | } | ||||||||
1674 | |||||||||
1675 | if (mit->numiter > 1 || mit->size == 0) { | ||||||||
1676 | /* | ||||||||
1677 | * If it is one, the inner loop checks indices, otherwise | ||||||||
1678 | * check indices beforehand, because it is much faster if | ||||||||
1679 | * broadcasting occurs and most likely no big overhead. | ||||||||
1680 | * The inner loop optimization skips index checks for size == 0 though. | ||||||||
1681 | */ | ||||||||
1682 | if (PyArray_MapIterCheckIndices(mit) < 0) { | ||||||||
1683 | goto finish; | ||||||||
1684 | } | ||||||||
1685 | } | ||||||||
1686 | |||||||||
1687 | /* Reset the outer iterator */ | ||||||||
1688 | if (NpyIter_Reset(mit->outer, NULL((void*)0)) < 0) { | ||||||||
1689 | goto finish; | ||||||||
1690 | } | ||||||||
1691 | |||||||||
1692 | if (mapiter_get(mit) < 0) { | ||||||||
1693 | goto finish; | ||||||||
1694 | } | ||||||||
1695 | |||||||||
1696 | result = (PyObject *)mit->extra_op; | ||||||||
1697 | Py_INCREF(result)_Py_INCREF(((PyObject*)(result))); | ||||||||
1698 | |||||||||
1699 | if (mit->consec) { | ||||||||
1700 | PyArray_MapIterSwapAxes(mit, (PyArrayObject **)&result, 1); | ||||||||
1701 | } | ||||||||
1702 | |||||||||
1703 | wrap_out_array: | ||||||||
1704 | if (!PyArray_CheckExact(self)(((PyObject*)(self))->ob_type == &PyArray_Type)) { | ||||||||
1705 | /* | ||||||||
1706 | * Need to create a new array as if the old one never existed. | ||||||||
1707 | */ | ||||||||
1708 | PyArrayObject *tmp_arr = (PyArrayObject *)result; | ||||||||
1709 | |||||||||
1710 | Py_INCREF(PyArray_DESCR(tmp_arr))_Py_INCREF(((PyObject*)(PyArray_DESCR(tmp_arr)))); | ||||||||
1711 | result = PyArray_NewFromDescrAndBase( | ||||||||
1712 | Py_TYPE(self)(((PyObject*)(self))->ob_type), | ||||||||
1713 | PyArray_DESCR(tmp_arr), | ||||||||
1714 | PyArray_NDIM(tmp_arr), | ||||||||
1715 | PyArray_SHAPE(tmp_arr), | ||||||||
1716 | PyArray_STRIDES(tmp_arr), | ||||||||
1717 | PyArray_BYTES(tmp_arr), | ||||||||
1718 | PyArray_FLAGS(tmp_arr), | ||||||||
1719 | (PyObject *)self, (PyObject *)tmp_arr); | ||||||||
1720 | Py_DECREF(tmp_arr)_Py_DECREF(((PyObject*)(tmp_arr))); | ||||||||
1721 | if (result == NULL((void*)0)) { | ||||||||
1722 | goto finish; | ||||||||
1723 | } | ||||||||
1724 | } | ||||||||
1725 | |||||||||
1726 | finish: | ||||||||
1727 | Py_XDECREF(mit)_Py_XDECREF(((PyObject*)(mit))); | ||||||||
1728 | Py_XDECREF(view)_Py_XDECREF(((PyObject*)(view))); | ||||||||
1729 | /* Clean up indices */ | ||||||||
1730 | for (i=0; i < index_num; i++) { | ||||||||
1731 | Py_XDECREF(indices[i].object)_Py_XDECREF(((PyObject*)(indices[i].object))); | ||||||||
1732 | } | ||||||||
1733 | return result; | ||||||||
1734 | } | ||||||||
1735 | |||||||||
1736 | |||||||||
1737 | /* | ||||||||
1738 | * Python C-Api level item assignment (implementation for PySequence_SetItem) | ||||||||
1739 | * | ||||||||
1740 | * Negative indices are not accepted because PySequence_SetItem converts | ||||||||
1741 | * them to positive indices before calling this. | ||||||||
1742 | */ | ||||||||
1743 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||
1744 | array_assign_item(PyArrayObject *self, Py_ssize_t i, PyObject *op) | ||||||||
1745 | { | ||||||||
1746 | npy_index_info indices[2]; | ||||||||
1747 | |||||||||
1748 | if (op == NULL((void*)0)) { | ||||||||
1749 | PyErr_SetString(PyExc_ValueError, | ||||||||
1750 | "cannot delete array elements"); | ||||||||
1751 | return -1; | ||||||||
1752 | } | ||||||||
1753 | if (PyArray_FailUnlessWriteable(self, "assignment destination") < 0) { | ||||||||
1754 | return -1; | ||||||||
1755 | } | ||||||||
1756 | if (PyArray_NDIM(self) == 0) { | ||||||||
1757 | PyErr_SetString(PyExc_IndexError, | ||||||||
1758 | "too many indices for array"); | ||||||||
1759 | return -1; | ||||||||
1760 | } | ||||||||
1761 | |||||||||
1762 | if (i < 0) { | ||||||||
1763 | /* This is an error, but undo PySequence_SetItem fix for message */ | ||||||||
1764 | i -= PyArray_DIM(self, 0); | ||||||||
1765 | } | ||||||||
1766 | |||||||||
1767 | indices[0].value = i; | ||||||||
1768 | indices[0].type = HAS_INTEGER; | ||||||||
1769 | if (PyArray_NDIM(self) == 1) { | ||||||||
1770 | char *item; | ||||||||
1771 | if (get_item_pointer(self, &item, indices, 1) < 0) { | ||||||||
1772 | return -1; | ||||||||
1773 | } | ||||||||
1774 | if (PyArray_Pack(PyArray_DESCR(self), item, op) < 0) { | ||||||||
1775 | return -1; | ||||||||
1776 | } | ||||||||
1777 | } | ||||||||
1778 | else { | ||||||||
1779 | PyArrayObject *view; | ||||||||
1780 | |||||||||
1781 | indices[1].value = PyArray_NDIM(self) - 1; | ||||||||
1782 | indices[1].type = HAS_ELLIPSIS; | ||||||||
1783 | if (get_view_from_index(self, &view, indices, 2, 0) < 0) { | ||||||||
1784 | return -1; | ||||||||
1785 | } | ||||||||
1786 | if (PyArray_CopyObject(view, op) < 0) { | ||||||||
1787 | Py_DECREF(view)_Py_DECREF(((PyObject*)(view))); | ||||||||
1788 | return -1; | ||||||||
1789 | } | ||||||||
1790 | Py_DECREF(view)_Py_DECREF(((PyObject*)(view))); | ||||||||
1791 | } | ||||||||
1792 | return 0; | ||||||||
1793 | } | ||||||||
1794 | |||||||||
1795 | |||||||||
1796 | /* | ||||||||
1797 | * General assignment with python indexing objects. | ||||||||
1798 | */ | ||||||||
1799 | static int | ||||||||
1800 | array_assign_subscript(PyArrayObject *self, PyObject *ind, PyObject *op) | ||||||||
1801 | { | ||||||||
1802 | int index_type; | ||||||||
1803 | int index_num; | ||||||||
1804 | int i, ndim, fancy_ndim; | ||||||||
1805 | PyArray_Descr *descr = PyArray_DESCR(self); | ||||||||
1806 | PyArrayObject *view = NULL((void*)0); | ||||||||
1807 | PyArrayObject *tmp_arr = NULL((void*)0); | ||||||||
1808 | npy_index_info indices[NPY_MAXDIMS32 * 2 + 1]; | ||||||||
1809 | |||||||||
1810 | PyArrayMapIterObject *mit = NULL((void*)0); | ||||||||
1811 | |||||||||
1812 | if (op == NULL((void*)0)) { | ||||||||
1813 | PyErr_SetString(PyExc_ValueError, | ||||||||
1814 | "cannot delete array elements"); | ||||||||
1815 | return -1; | ||||||||
1816 | } | ||||||||
1817 | if (PyArray_FailUnlessWriteable(self, "assignment destination") < 0) { | ||||||||
1818 | return -1; | ||||||||
1819 | } | ||||||||
1820 | |||||||||
1821 | /* field access */ | ||||||||
1822 | if (PyDataType_HASFIELDS(PyArray_DESCR(self))(((PyArray_Descr *)(PyArray_DESCR(self)))->names != ((void *)0))){ | ||||||||
1823 | PyArrayObject *view; | ||||||||
1824 | int ret = _get_field_view(self, ind, &view); | ||||||||
1825 | if (ret == 0){ | ||||||||
1826 | if (view == NULL((void*)0)) { | ||||||||
1827 | return -1; | ||||||||
1828 | } | ||||||||
1829 | if (PyArray_CopyObject(view, op) < 0) { | ||||||||
1830 | Py_DECREF(view)_Py_DECREF(((PyObject*)(view))); | ||||||||
1831 | return -1; | ||||||||
1832 | } | ||||||||
1833 | Py_DECREF(view)_Py_DECREF(((PyObject*)(view))); | ||||||||
1834 | return 0; | ||||||||
1835 | } | ||||||||
1836 | } | ||||||||
1837 | |||||||||
1838 | /* Prepare the indices */ | ||||||||
1839 | index_type = prepare_index(self, ind, indices, &index_num, | ||||||||
1840 | &ndim, &fancy_ndim, 1); | ||||||||
1841 | |||||||||
1842 | if (index_type < 0) { | ||||||||
1843 | return -1; | ||||||||
1844 | } | ||||||||
1845 | |||||||||
1846 | /* Full integer index */ | ||||||||
1847 | if (index_type == HAS_INTEGER) { | ||||||||
1848 | char *item; | ||||||||
1849 | if (get_item_pointer(self, &item, indices, index_num) < 0) { | ||||||||
1850 | return -1; | ||||||||
1851 | } | ||||||||
1852 | if (PyArray_Pack(PyArray_DESCR(self), item, op) < 0) { | ||||||||
1853 | return -1; | ||||||||
1854 | } | ||||||||
1855 | /* integers do not store objects in indices */ | ||||||||
1856 | return 0; | ||||||||
1857 | } | ||||||||
1858 | |||||||||
1859 | /* Single boolean array */ | ||||||||
1860 | if (index_type == HAS_BOOL) { | ||||||||
1861 | if (!PyArray_Check(op)((((PyObject*)(op))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(op))->ob_type), (&PyArray_Type)))) { | ||||||||
1862 | Py_INCREF(PyArray_DESCR(self))_Py_INCREF(((PyObject*)(PyArray_DESCR(self)))); | ||||||||
1863 | tmp_arr = (PyArrayObject *)PyArray_FromAny(op, | ||||||||
1864 | PyArray_DESCR(self), 0, 0, | ||||||||
1865 | NPY_ARRAY_FORCECAST0x0010, NULL((void*)0)); | ||||||||
1866 | if (tmp_arr == NULL((void*)0)) { | ||||||||
1867 | goto fail; | ||||||||
1868 | } | ||||||||
1869 | } | ||||||||
1870 | else { | ||||||||
1871 | Py_INCREF(op)_Py_INCREF(((PyObject*)(op))); | ||||||||
1872 | tmp_arr = (PyArrayObject *)op; | ||||||||
1873 | } | ||||||||
1874 | |||||||||
1875 | if (array_assign_boolean_subscript(self, | ||||||||
1876 | (PyArrayObject *)indices[0].object, | ||||||||
1877 | tmp_arr, NPY_CORDER) < 0) { | ||||||||
1878 | goto fail; | ||||||||
1879 | } | ||||||||
1880 | goto success; | ||||||||
1881 | } | ||||||||
1882 | |||||||||
1883 | |||||||||
1884 | /* | ||||||||
1885 | * Single ellipsis index, no need to create a new view. | ||||||||
1886 | * Note that here, we do *not* go through self.__getitem__ for subclasses | ||||||||
1887 | * (defchar array failed then, due to uninitialized values...) | ||||||||
1888 | */ | ||||||||
1889 | else if (index_type == HAS_ELLIPSIS) { | ||||||||
1890 | if ((PyObject *)self == op) { | ||||||||
1891 | /* | ||||||||
1892 | * CopyObject does not handle this case gracefully and | ||||||||
1893 | * there is nothing to do. Removing the special case | ||||||||
1894 | * will cause segfaults, though it is unclear what exactly | ||||||||
1895 | * happens. | ||||||||
1896 | */ | ||||||||
1897 | return 0; | ||||||||
1898 | } | ||||||||
1899 | /* we can just use self, but incref for error handling */ | ||||||||
1900 | Py_INCREF((PyObject *)self)_Py_INCREF(((PyObject*)((PyObject *)self))); | ||||||||
1901 | view = self; | ||||||||
1902 | } | ||||||||
1903 | |||||||||
1904 | /* | ||||||||
1905 | * WARNING: There is a huge special case here. If this is not a | ||||||||
1906 | * base class array, we have to get the view through its | ||||||||
1907 | * very own index machinery. | ||||||||
1908 | * Many subclasses should probably call __setitem__ | ||||||||
1909 | * with a base class ndarray view to avoid this. | ||||||||
1910 | */ | ||||||||
1911 | else if (!(index_type & (HAS_FANCY | HAS_SCALAR_ARRAY)) | ||||||||
1912 | && !PyArray_CheckExact(self)(((PyObject*)(self))->ob_type == &PyArray_Type)) { | ||||||||
1913 | view = (PyArrayObject *)PyObject_GetItem((PyObject *)self, ind); | ||||||||
1914 | if (view == NULL((void*)0)) { | ||||||||
1915 | goto fail; | ||||||||
1916 | } | ||||||||
1917 | if (!PyArray_Check(view)((((PyObject*)(view))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(view))->ob_type), (&PyArray_Type)))) { | ||||||||
1918 | PyErr_SetString(PyExc_RuntimeError, | ||||||||
1919 | "Getitem not returning array"); | ||||||||
1920 | goto fail; | ||||||||
1921 | } | ||||||||
1922 | } | ||||||||
1923 | |||||||||
1924 | /* | ||||||||
1925 | * View based indexing. | ||||||||
1926 | * There are two cases here. First we need to create a simple view, | ||||||||
1927 | * second we need to create a (possibly invalid) view for the | ||||||||
1928 | * subspace to the fancy index. This procedure is identical. | ||||||||
1929 | */ | ||||||||
1930 | else if (index_type & (HAS_SLICE | HAS_NEWAXIS | | ||||||||
1931 | HAS_ELLIPSIS | HAS_INTEGER)) { | ||||||||
1932 | if (get_view_from_index(self, &view, indices, index_num, | ||||||||
1933 | (index_type & HAS_FANCY)) < 0) { | ||||||||
1934 | goto fail; | ||||||||
1935 | } | ||||||||
1936 | } | ||||||||
1937 | else { | ||||||||
1938 | view = NULL((void*)0); | ||||||||
1939 | } | ||||||||
1940 | |||||||||
1941 | /* If there is no fancy indexing, we have the array to assign to */ | ||||||||
1942 | if (!(index_type & HAS_FANCY)) { | ||||||||
1943 | if (PyArray_CopyObject(view, op) < 0) { | ||||||||
1944 | goto fail; | ||||||||
1945 | } | ||||||||
1946 | goto success; | ||||||||
1947 | } | ||||||||
1948 | |||||||||
1949 | if (!PyArray_Check(op)((((PyObject*)(op))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(op))->ob_type), (&PyArray_Type)))) { | ||||||||
1950 | /* | ||||||||
1951 | * If the array is of object converting the values to an array | ||||||||
1952 | * might not be legal even though normal assignment works. | ||||||||
1953 | * So allocate a temporary array of the right size and use the | ||||||||
1954 | * normal assignment to handle this case. | ||||||||
1955 | */ | ||||||||
1956 | if (PyDataType_REFCHK(descr)(((descr)->flags & (0x01)) == (0x01)) && PySequence_Check(op)) { | ||||||||
1957 | tmp_arr = NULL((void*)0); | ||||||||
1958 | } | ||||||||
1959 | else { | ||||||||
1960 | /* There is nothing fancy possible, so just make an array */ | ||||||||
1961 | Py_INCREF(descr)_Py_INCREF(((PyObject*)(descr))); | ||||||||
1962 | tmp_arr = (PyArrayObject *)PyArray_FromAny(op, descr, 0, 0, | ||||||||
1963 | NPY_ARRAY_FORCECAST0x0010, NULL((void*)0)); | ||||||||
1964 | if (tmp_arr == NULL((void*)0)) { | ||||||||
1965 | goto fail; | ||||||||
1966 | } | ||||||||
1967 | } | ||||||||
1968 | } | ||||||||
1969 | else { | ||||||||
1970 | Py_INCREF(op)_Py_INCREF(((PyObject*)(op))); | ||||||||
1971 | tmp_arr = (PyArrayObject *)op; | ||||||||
1972 | } | ||||||||
1973 | |||||||||
1974 | /* | ||||||||
1975 | * Special case for very simple 1-d fancy indexing, which however | ||||||||
1976 | * is quite common. This saves not only a lot of setup time in the | ||||||||
1977 | * iterator, but also is faster (must be exactly fancy because | ||||||||
1978 | * we don't support 0-d booleans here) | ||||||||
1979 | */ | ||||||||
1980 | if (index_type == HAS_FANCY && | ||||||||
1981 | index_num == 1 && tmp_arr) { | ||||||||
1982 | /* The array being indexed has one dimension and it is a fancy index */ | ||||||||
1983 | PyArrayObject *ind = (PyArrayObject*)indices[0].object; | ||||||||
1984 | |||||||||
1985 | /* Check if the type is equivalent */ | ||||||||
1986 | if (PyArray_EquivTypes(PyArray_DESCR(self), | ||||||||
1987 | PyArray_DESCR(tmp_arr)) && | ||||||||
1988 | /* | ||||||||
1989 | * Either they are equivalent, or the values must | ||||||||
1990 | * be a scalar | ||||||||
1991 | */ | ||||||||
1992 | (PyArray_EQUIVALENTLY_ITERABLE(ind, tmp_arr,( ( PyArray_NDIM(ind) == PyArray_NDIM(tmp_arr) && PyArray_CompareLists (PyArray_DIMS(ind), PyArray_DIMS(tmp_arr), PyArray_NDIM(ind)) && (PyArray_FLAGS(ind)&(0x0001| 0x0002)) & ( PyArray_FLAGS(tmp_arr)&(0x0001| 0x0002)) ) && PyArray_EQUIVALENTLY_ITERABLE_OVERLAP_OK ( ind, tmp_arr, 1, 1)) | ||||||||
1993 | PyArray_TRIVIALLY_ITERABLE_OP_READ,( ( PyArray_NDIM(ind) == PyArray_NDIM(tmp_arr) && PyArray_CompareLists (PyArray_DIMS(ind), PyArray_DIMS(tmp_arr), PyArray_NDIM(ind)) && (PyArray_FLAGS(ind)&(0x0001| 0x0002)) & ( PyArray_FLAGS(tmp_arr)&(0x0001| 0x0002)) ) && PyArray_EQUIVALENTLY_ITERABLE_OVERLAP_OK ( ind, tmp_arr, 1, 1)) | ||||||||
1994 | PyArray_TRIVIALLY_ITERABLE_OP_READ)( ( PyArray_NDIM(ind) == PyArray_NDIM(tmp_arr) && PyArray_CompareLists (PyArray_DIMS(ind), PyArray_DIMS(tmp_arr), PyArray_NDIM(ind)) && (PyArray_FLAGS(ind)&(0x0001| 0x0002)) & ( PyArray_FLAGS(tmp_arr)&(0x0001| 0x0002)) ) && PyArray_EQUIVALENTLY_ITERABLE_OVERLAP_OK ( ind, tmp_arr, 1, 1)) || | ||||||||
1995 | (PyArray_NDIM(tmp_arr) == 0 && | ||||||||
1996 | PyArray_TRIVIALLY_ITERABLE(ind)( PyArray_NDIM(ind) <= 1 || PyArray_CHKFLAGS(ind, 0x0001) || PyArray_CHKFLAGS(ind, 0x0002) ))) && | ||||||||
1997 | /* Check if the type is equivalent to INTP */ | ||||||||
1998 | PyArray_ITEMSIZE(ind) == sizeof(npy_intp) && | ||||||||
1999 | PyArray_DESCR(ind)->kind == 'i' && | ||||||||
2000 | IsUintAligned(ind) && | ||||||||
2001 | PyDataType_ISNOTSWAPPED(PyArray_DESCR(ind))((((PyArray_Descr *)(PyArray_DESCR(ind)))->byteorder) != '>' )) { | ||||||||
2002 | |||||||||
2003 | /* trivial_set checks the index for us */ | ||||||||
2004 | if (mapiter_trivial_set(self, ind, tmp_arr) < 0) { | ||||||||
2005 | goto fail; | ||||||||
2006 | } | ||||||||
2007 | goto success; | ||||||||
2008 | } | ||||||||
2009 | } | ||||||||
2010 | |||||||||
2011 | /* | ||||||||
2012 | * NOTE: If tmp_arr was not allocated yet, mit should | ||||||||
2013 | * handle the allocation. | ||||||||
2014 | * The NPY_ITER_READWRITE is necessary for automatic | ||||||||
2015 | * allocation. Readwrite would not allow broadcasting | ||||||||
2016 | * correctly, but such an operand always has the full | ||||||||
2017 | * size anyway. | ||||||||
2018 | */ | ||||||||
2019 | mit = (PyArrayMapIterObject *)PyArray_MapIterNew(indices, | ||||||||
2020 | index_num, index_type, | ||||||||
2021 | ndim, fancy_ndim, self, | ||||||||
2022 | view, 0, | ||||||||
2023 | NPY_ITER_WRITEONLY0x00040000, | ||||||||
2024 | ((tmp_arr == NULL((void*)0)) ? | ||||||||
2025 | NPY_ITER_READWRITE0x00010000 : | ||||||||
2026 | NPY_ITER_READONLY0x00020000), | ||||||||
2027 | tmp_arr, descr); | ||||||||
2028 | |||||||||
2029 | if (mit == NULL((void*)0)) { | ||||||||
2030 | goto fail; | ||||||||
2031 | } | ||||||||
2032 | |||||||||
2033 | if (tmp_arr == NULL((void*)0)) { | ||||||||
2034 | /* Fill extra op, need to swap first */ | ||||||||
2035 | tmp_arr = mit->extra_op; | ||||||||
2036 | Py_INCREF(tmp_arr)_Py_INCREF(((PyObject*)(tmp_arr))); | ||||||||
2037 | if (mit->consec) { | ||||||||
2038 | PyArray_MapIterSwapAxes(mit, &tmp_arr, 1); | ||||||||
2039 | if (tmp_arr == NULL((void*)0)) { | ||||||||
2040 | goto fail; | ||||||||
2041 | } | ||||||||
2042 | } | ||||||||
2043 | if (PyArray_CopyObject(tmp_arr, op) < 0) { | ||||||||
2044 | goto fail; | ||||||||
2045 | } | ||||||||
2046 | } | ||||||||
2047 | |||||||||
2048 | /* Can now reset the outer iterator (delayed bufalloc) */ | ||||||||
2049 | if (NpyIter_Reset(mit->outer, NULL((void*)0)) < 0) { | ||||||||
2050 | goto fail; | ||||||||
2051 | } | ||||||||
2052 | |||||||||
2053 | if (PyArray_MapIterCheckIndices(mit) < 0) { | ||||||||
2054 | goto fail; | ||||||||
2055 | } | ||||||||
2056 | |||||||||
2057 | /* | ||||||||
2058 | * Could add a casting check, but apparently most assignments do | ||||||||
2059 | * not care about safe casting. | ||||||||
2060 | */ | ||||||||
2061 | |||||||||
2062 | if (mapiter_set(mit) < 0) { | ||||||||
2063 | goto fail; | ||||||||
2064 | } | ||||||||
2065 | |||||||||
2066 | Py_DECREF(mit)_Py_DECREF(((PyObject*)(mit))); | ||||||||
2067 | goto success; | ||||||||
2068 | |||||||||
2069 | /* Clean up temporary variables and indices */ | ||||||||
2070 | fail: | ||||||||
2071 | Py_XDECREF((PyObject *)view)_Py_XDECREF(((PyObject*)((PyObject *)view))); | ||||||||
2072 | Py_XDECREF((PyObject *)tmp_arr)_Py_XDECREF(((PyObject*)((PyObject *)tmp_arr))); | ||||||||
2073 | Py_XDECREF((PyObject *)mit)_Py_XDECREF(((PyObject*)((PyObject *)mit))); | ||||||||
2074 | for (i=0; i < index_num; i++) { | ||||||||
2075 | Py_XDECREF(indices[i].object)_Py_XDECREF(((PyObject*)(indices[i].object))); | ||||||||
2076 | } | ||||||||
2077 | return -1; | ||||||||
2078 | |||||||||
2079 | success: | ||||||||
2080 | Py_XDECREF((PyObject *)view)_Py_XDECREF(((PyObject*)((PyObject *)view))); | ||||||||
2081 | Py_XDECREF((PyObject *)tmp_arr)_Py_XDECREF(((PyObject*)((PyObject *)tmp_arr))); | ||||||||
2082 | for (i=0; i < index_num; i++) { | ||||||||
2083 | Py_XDECREF(indices[i].object)_Py_XDECREF(((PyObject*)(indices[i].object))); | ||||||||
2084 | } | ||||||||
2085 | return 0; | ||||||||
2086 | } | ||||||||
2087 | |||||||||
2088 | |||||||||
2089 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyMappingMethods array_as_mapping = { | ||||||||
2090 | (lenfunc)array_length, /*mp_length*/ | ||||||||
2091 | (binaryfunc)array_subscript, /*mp_subscript*/ | ||||||||
2092 | (objobjargproc)array_assign_subscript, /*mp_ass_subscript*/ | ||||||||
2093 | }; | ||||||||
2094 | |||||||||
2095 | /****************** End of Mapping Protocol ******************************/ | ||||||||
2096 | |||||||||
2097 | /*********************** Subscript Array Iterator ************************* | ||||||||
2098 | * * | ||||||||
2099 | * This object handles subscript behavior for array objects. * | ||||||||
2100 | * It is an iterator object with a next method * | ||||||||
2101 | * It abstracts the n-dimensional mapping behavior to make the looping * | ||||||||
2102 | * code more understandable (maybe) * | ||||||||
2103 | * and so that indexing can be set up ahead of time * | ||||||||
2104 | */ | ||||||||
2105 | |||||||||
2106 | /* | ||||||||
2107 | * This function takes a Boolean array and constructs index objects and | ||||||||
2108 | * iterators as if nonzero(Bool) had been called | ||||||||
2109 | * | ||||||||
2110 | * Must not be called on a 0-d array. | ||||||||
2111 | */ | ||||||||
2112 | static int | ||||||||
2113 | _nonzero_indices(PyObject *myBool, PyArrayObject **arrays) | ||||||||
2114 | { | ||||||||
2115 | PyArray_Descr *typecode; | ||||||||
2116 | PyArrayObject *ba = NULL((void*)0), *new = NULL((void*)0); | ||||||||
2117 | int nd, j; | ||||||||
2118 | npy_intp size, i, count; | ||||||||
2119 | npy_bool *ptr; | ||||||||
2120 | npy_intp coords[NPY_MAXDIMS32], dims_m1[NPY_MAXDIMS32]; | ||||||||
2121 | npy_intp *dptr[NPY_MAXDIMS32]; | ||||||||
2122 | static npy_intp one = 1; | ||||||||
2123 | NPY_BEGIN_THREADS_DEFPyThreadState *_save=((void*)0);; | ||||||||
2124 | |||||||||
2125 | typecode=PyArray_DescrFromType(NPY_BOOL); | ||||||||
2126 | ba = (PyArrayObject *)PyArray_FromAny(myBool, typecode, 0, 0, | ||||||||
2127 | NPY_ARRAY_CARRAY(0x0001 | (0x0100 | 0x0400)), NULL((void*)0)); | ||||||||
2128 | if (ba == NULL((void*)0)) { | ||||||||
2129 | return -1; | ||||||||
2130 | } | ||||||||
2131 | nd = PyArray_NDIM(ba); | ||||||||
2132 | |||||||||
2133 | for (j = 0; j < nd; j++) { | ||||||||
2134 | arrays[j] = NULL((void*)0); | ||||||||
2135 | } | ||||||||
2136 | size = PyArray_SIZE(ba)PyArray_MultiplyList(PyArray_DIMS(ba), PyArray_NDIM(ba)); | ||||||||
2137 | ptr = (npy_bool *)PyArray_DATA(ba); | ||||||||
2138 | |||||||||
2139 | /* | ||||||||
2140 | * pre-determine how many nonzero entries there are, | ||||||||
2141 | * ignore dimensionality of input as its a CARRAY | ||||||||
2142 | */ | ||||||||
2143 | count = count_boolean_trues(1, (char*)ptr, &size, &one); | ||||||||
2144 | |||||||||
2145 | /* create count-sized index arrays for each dimension */ | ||||||||
2146 | for (j = 0; j < nd; j++) { | ||||||||
2147 | new = (PyArrayObject *)PyArray_NewFromDescr( | ||||||||
2148 | &PyArray_Type, PyArray_DescrFromType(NPY_INTPNPY_LONG), | ||||||||
2149 | 1, &count, NULL((void*)0), NULL((void*)0), | ||||||||
2150 | 0, NULL((void*)0)); | ||||||||
2151 | if (new == NULL((void*)0)) { | ||||||||
2152 | goto fail; | ||||||||
2153 | } | ||||||||
2154 | arrays[j] = new; | ||||||||
2155 | |||||||||
2156 | dptr[j] = (npy_intp *)PyArray_DATA(new); | ||||||||
2157 | coords[j] = 0; | ||||||||
2158 | dims_m1[j] = PyArray_DIMS(ba)[j]-1; | ||||||||
2159 | } | ||||||||
2160 | if (count == 0) { | ||||||||
2161 | goto finish; | ||||||||
2162 | } | ||||||||
2163 | |||||||||
2164 | /* | ||||||||
2165 | * Loop through the Boolean array and copy coordinates | ||||||||
2166 | * for non-zero entries | ||||||||
2167 | */ | ||||||||
2168 | NPY_BEGIN_THREADS_THRESHOLDED(size)do { if ((size) > 500) { _save = PyEval_SaveThread();} } while (0);; | ||||||||
2169 | for (i = 0; i < size; i++) { | ||||||||
2170 | if (*(ptr++)) { | ||||||||
2171 | for (j = 0; j < nd; j++) { | ||||||||
2172 | *(dptr[j]++) = coords[j]; | ||||||||
2173 | } | ||||||||
2174 | } | ||||||||
2175 | /* Borrowed from ITER_NEXT macro */ | ||||||||
2176 | for (j = nd - 1; j >= 0; j--) { | ||||||||
2177 | if (coords[j] < dims_m1[j]) { | ||||||||
2178 | coords[j]++; | ||||||||
2179 | break; | ||||||||
2180 | } | ||||||||
2181 | else { | ||||||||
2182 | coords[j] = 0; | ||||||||
2183 | } | ||||||||
2184 | } | ||||||||
2185 | } | ||||||||
2186 | NPY_END_THREADSdo { if (_save) { PyEval_RestoreThread(_save); _save = ((void *)0);} } while (0);; | ||||||||
2187 | |||||||||
2188 | finish: | ||||||||
2189 | Py_DECREF(ba)_Py_DECREF(((PyObject*)(ba))); | ||||||||
2190 | return nd; | ||||||||
2191 | |||||||||
2192 | fail: | ||||||||
2193 | for (j = 0; j < nd; j++) { | ||||||||
2194 | Py_XDECREF(arrays[j])_Py_XDECREF(((PyObject*)(arrays[j]))); | ||||||||
2195 | } | ||||||||
2196 | Py_XDECREF(ba)_Py_XDECREF(((PyObject*)(ba))); | ||||||||
2197 | return -1; | ||||||||
2198 | } | ||||||||
2199 | |||||||||
2200 | |||||||||
2201 | /* Reset the map iterator to the beginning */ | ||||||||
2202 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) void | ||||||||
2203 | PyArray_MapIterReset(PyArrayMapIterObject *mit) | ||||||||
2204 | { | ||||||||
2205 | npy_intp indval; | ||||||||
2206 | char *baseptrs[2]; | ||||||||
2207 | int i; | ||||||||
2208 | |||||||||
2209 | if (mit->size == 0) { | ||||||||
2210 | return; | ||||||||
2211 | } | ||||||||
2212 | |||||||||
2213 | NpyIter_Reset(mit->outer, NULL((void*)0)); | ||||||||
2214 | if (mit->extra_op_iter) { | ||||||||
2215 | NpyIter_Reset(mit->extra_op_iter, NULL((void*)0)); | ||||||||
2216 | |||||||||
2217 | baseptrs[1] = mit->extra_op_ptrs[0]; | ||||||||
2218 | } | ||||||||
2219 | |||||||||
2220 | baseptrs[0] = mit->baseoffset; | ||||||||
2221 | |||||||||
2222 | for (i = 0; i < mit->numiter; i++) { | ||||||||
2223 | indval = *((npy_intp*)mit->outer_ptrs[i]); | ||||||||
2224 | if (indval < 0) { | ||||||||
2225 | indval += mit->fancy_dims[i]; | ||||||||
2226 | } | ||||||||
2227 | baseptrs[0] += indval * mit->fancy_strides[i]; | ||||||||
2228 | } | ||||||||
2229 | mit->dataptr = baseptrs[0]; | ||||||||
2230 | |||||||||
2231 | if (mit->subspace_iter) { | ||||||||
2232 | NpyIter_ResetBasePointers(mit->subspace_iter, baseptrs, NULL((void*)0)); | ||||||||
2233 | mit->iter_count = *NpyIter_GetInnerLoopSizePtr(mit->subspace_iter); | ||||||||
2234 | } | ||||||||
2235 | else { | ||||||||
2236 | mit->iter_count = *NpyIter_GetInnerLoopSizePtr(mit->outer); | ||||||||
2237 | } | ||||||||
2238 | |||||||||
2239 | return; | ||||||||
2240 | } | ||||||||
2241 | |||||||||
2242 | |||||||||
2243 | /*NUMPY_API | ||||||||
2244 | * This function needs to update the state of the map iterator | ||||||||
2245 | * and point mit->dataptr to the memory-location of the next object | ||||||||
2246 | * | ||||||||
2247 | * Note that this function never handles an extra operand but provides | ||||||||
2248 | * compatibility for an old (exposed) API. | ||||||||
2249 | */ | ||||||||
2250 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) void | ||||||||
2251 | PyArray_MapIterNext(PyArrayMapIterObject *mit) | ||||||||
2252 | { | ||||||||
2253 | int i; | ||||||||
2254 | char *baseptr; | ||||||||
2255 | npy_intp indval; | ||||||||
2256 | |||||||||
2257 | if (mit->subspace_iter) { | ||||||||
2258 | if (--mit->iter_count > 0) { | ||||||||
2259 | mit->subspace_ptrs[0] += mit->subspace_strides[0]; | ||||||||
2260 | mit->dataptr = mit->subspace_ptrs[0]; | ||||||||
2261 | return; | ||||||||
2262 | } | ||||||||
2263 | else if (mit->subspace_next(mit->subspace_iter)) { | ||||||||
2264 | mit->iter_count = *NpyIter_GetInnerLoopSizePtr(mit->subspace_iter); | ||||||||
2265 | mit->dataptr = mit->subspace_ptrs[0]; | ||||||||
2266 | } | ||||||||
2267 | else { | ||||||||
2268 | if (!mit->outer_next(mit->outer)) { | ||||||||
2269 | return; | ||||||||
2270 | } | ||||||||
2271 | |||||||||
2272 | baseptr = mit->baseoffset; | ||||||||
2273 | |||||||||
2274 | for (i = 0; i < mit->numiter; i++) { | ||||||||
2275 | indval = *((npy_intp*)mit->outer_ptrs[i]); | ||||||||
2276 | if (indval < 0) { | ||||||||
2277 | indval += mit->fancy_dims[i]; | ||||||||
2278 | } | ||||||||
2279 | baseptr += indval * mit->fancy_strides[i]; | ||||||||
2280 | } | ||||||||
2281 | NpyIter_ResetBasePointers(mit->subspace_iter, &baseptr, NULL((void*)0)); | ||||||||
2282 | mit->iter_count = *NpyIter_GetInnerLoopSizePtr(mit->subspace_iter); | ||||||||
2283 | |||||||||
2284 | mit->dataptr = mit->subspace_ptrs[0]; | ||||||||
2285 | } | ||||||||
2286 | } | ||||||||
2287 | else { | ||||||||
2288 | if (--mit->iter_count > 0) { | ||||||||
2289 | baseptr = mit->baseoffset; | ||||||||
2290 | |||||||||
2291 | for (i = 0; i < mit->numiter; i++) { | ||||||||
2292 | mit->outer_ptrs[i] += mit->outer_strides[i]; | ||||||||
2293 | |||||||||
2294 | indval = *((npy_intp*)mit->outer_ptrs[i]); | ||||||||
2295 | if (indval < 0) { | ||||||||
2296 | indval += mit->fancy_dims[i]; | ||||||||
2297 | } | ||||||||
2298 | baseptr += indval * mit->fancy_strides[i]; | ||||||||
2299 | } | ||||||||
2300 | |||||||||
2301 | mit->dataptr = baseptr; | ||||||||
2302 | return; | ||||||||
2303 | } | ||||||||
2304 | else { | ||||||||
2305 | if (!mit->outer_next(mit->outer)) { | ||||||||
2306 | return; | ||||||||
2307 | } | ||||||||
2308 | mit->iter_count = *NpyIter_GetInnerLoopSizePtr(mit->outer); | ||||||||
2309 | baseptr = mit->baseoffset; | ||||||||
2310 | |||||||||
2311 | for (i = 0; i < mit->numiter; i++) { | ||||||||
2312 | indval = *((npy_intp*)mit->outer_ptrs[i]); | ||||||||
2313 | if (indval < 0) { | ||||||||
2314 | indval += mit->fancy_dims[i]; | ||||||||
2315 | } | ||||||||
2316 | baseptr += indval * mit->fancy_strides[i]; | ||||||||
2317 | } | ||||||||
2318 | |||||||||
2319 | mit->dataptr = baseptr; | ||||||||
2320 | } | ||||||||
2321 | } | ||||||||
2322 | } | ||||||||
2323 | |||||||||
2324 | |||||||||
2325 | /** | ||||||||
2326 | * Fill information about the iterator. The MapIterObject does not | ||||||||
2327 | * need to have any information set for this function to work. | ||||||||
2328 | * (PyArray_MapIterSwapAxes requires also nd and nd_fancy info) | ||||||||
2329 | * | ||||||||
2330 | * Sets the following information: | ||||||||
2331 | * * mit->consec: The axis where the fancy indices need transposing to. | ||||||||
2332 | * * mit->iteraxes: The axis which the fancy index corresponds to. | ||||||||
2333 | * * mit-> fancy_dims: the dimension of `arr` along the indexed dimension | ||||||||
2334 | * for each fancy index. | ||||||||
2335 | * * mit->fancy_strides: the strides for the dimension being indexed | ||||||||
2336 | * by each fancy index. | ||||||||
2337 | * * mit->dimensions: Broadcast dimension of the fancy indices and | ||||||||
2338 | * the subspace iteration dimension. | ||||||||
2339 | * | ||||||||
2340 | * @param MapIterObject | ||||||||
2341 | * @param The parsed indices object | ||||||||
2342 | * @param Number of indices | ||||||||
2343 | * @param The array that is being iterated | ||||||||
2344 | * | ||||||||
2345 | * @return 0 on success -1 on failure (broadcasting or too many fancy indices) | ||||||||
2346 | */ | ||||||||
2347 | static int | ||||||||
2348 | mapiter_fill_info(PyArrayMapIterObject *mit, npy_index_info *indices, | ||||||||
2349 | int index_num, PyArrayObject *arr) | ||||||||
2350 | { | ||||||||
2351 | int j = 0, i; | ||||||||
2352 | int curr_dim = 0; | ||||||||
2353 | /* dimension of index result (up to first fancy index) */ | ||||||||
2354 | int result_dim = 0; | ||||||||
2355 | /* -1 init; 0 found fancy; 1 fancy stopped; 2 found not consecutive fancy */ | ||||||||
2356 | int consec_status = -1; | ||||||||
2357 | int axis, broadcast_axis; | ||||||||
2358 | npy_intp dimension; | ||||||||
2359 | |||||||||
2360 | for (i = 0; i < mit->nd_fancy; i++) { | ||||||||
2361 | mit->dimensions[i] = 1; | ||||||||
2362 | } | ||||||||
2363 | |||||||||
2364 | mit->consec = 0; | ||||||||
2365 | for (i = 0; i < index_num; i++) { | ||||||||
2366 | /* integer and fancy indexes are transposed together */ | ||||||||
2367 | if (indices[i].type & (HAS_FANCY | HAS_INTEGER)) { | ||||||||
2368 | /* there was no previous fancy index, so set consec */ | ||||||||
2369 | if (consec_status == -1) { | ||||||||
2370 | mit->consec = result_dim; | ||||||||
2371 | consec_status = 0; | ||||||||
2372 | } | ||||||||
2373 | /* there was already a non-fancy index after a fancy one */ | ||||||||
2374 | else if (consec_status == 1) { | ||||||||
2375 | consec_status = 2; | ||||||||
2376 | mit->consec = 0; | ||||||||
2377 | } | ||||||||
2378 | } | ||||||||
2379 | else { | ||||||||
2380 | /* consec_status == 0 means there was a fancy index before */ | ||||||||
2381 | if (consec_status == 0) { | ||||||||
2382 | consec_status = 1; | ||||||||
2383 | } | ||||||||
2384 | } | ||||||||
2385 | |||||||||
2386 | /* Before contunuing, ensure that there are not too fancy indices */ | ||||||||
2387 | if (indices[i].type & HAS_FANCY) { | ||||||||
2388 | if (NPY_UNLIKELY(j >= NPY_MAXDIMS)__builtin_expect(!!(j >= 32), 0)) { | ||||||||
2389 | PyErr_Format(PyExc_IndexError, | ||||||||
2390 | "too many advanced (array) indices. This probably " | ||||||||
2391 | "means you are indexing with too many booleans. " | ||||||||
2392 | "(more than %d found)", NPY_MAXDIMS32); | ||||||||
2393 | return -1; | ||||||||
2394 | } | ||||||||
2395 | } | ||||||||
2396 | |||||||||
2397 | /* (iterating) fancy index, store the iterator */ | ||||||||
2398 | if (indices[i].type == HAS_FANCY) { | ||||||||
2399 | mit->fancy_strides[j] = PyArray_STRIDE(arr, curr_dim); | ||||||||
2400 | mit->fancy_dims[j] = PyArray_DIM(arr, curr_dim); | ||||||||
2401 | mit->iteraxes[j++] = curr_dim++; | ||||||||
2402 | |||||||||
2403 | /* Check broadcasting */ | ||||||||
2404 | broadcast_axis = mit->nd_fancy; | ||||||||
2405 | /* Fill from back, we know how many dims there are */ | ||||||||
2406 | for (axis = PyArray_NDIM((PyArrayObject *)indices[i].object) - 1; | ||||||||
2407 | axis >= 0; axis--) { | ||||||||
2408 | broadcast_axis--; | ||||||||
2409 | dimension = PyArray_DIM((PyArrayObject *)indices[i].object, axis); | ||||||||
2410 | |||||||||
2411 | /* If it is 1, we can broadcast */ | ||||||||
2412 | if (dimension != 1) { | ||||||||
2413 | if (dimension != mit->dimensions[broadcast_axis]) { | ||||||||
2414 | if (mit->dimensions[broadcast_axis] != 1) { | ||||||||
2415 | goto broadcast_error; | ||||||||
2416 | } | ||||||||
2417 | mit->dimensions[broadcast_axis] = dimension; | ||||||||
2418 | } | ||||||||
2419 | } | ||||||||
2420 | } | ||||||||
2421 | } | ||||||||
2422 | else if (indices[i].type == HAS_0D_BOOL) { | ||||||||
2423 | mit->fancy_strides[j] = 0; | ||||||||
2424 | mit->fancy_dims[j] = 1; | ||||||||
2425 | /* Does not exist */ | ||||||||
2426 | mit->iteraxes[j++] = -1; | ||||||||
2427 | if ((indices[i].value == 0) && | ||||||||
2428 | (mit->dimensions[mit->nd_fancy - 1]) > 1) { | ||||||||
2429 | goto broadcast_error; | ||||||||
2430 | } | ||||||||
2431 | mit->dimensions[mit->nd_fancy-1] *= indices[i].value; | ||||||||
2432 | } | ||||||||
2433 | |||||||||
2434 | /* advance curr_dim for non-fancy indices */ | ||||||||
2435 | else if (indices[i].type == HAS_ELLIPSIS) { | ||||||||
2436 | curr_dim += (int)indices[i].value; | ||||||||
2437 | result_dim += (int)indices[i].value; | ||||||||
2438 | } | ||||||||
2439 | else if (indices[i].type != HAS_NEWAXIS){ | ||||||||
2440 | curr_dim += 1; | ||||||||
2441 | result_dim += 1; | ||||||||
2442 | } | ||||||||
2443 | else { | ||||||||
2444 | result_dim += 1; | ||||||||
2445 | } | ||||||||
2446 | } | ||||||||
2447 | |||||||||
2448 | /* Fill dimension of subspace */ | ||||||||
2449 | if (mit->subspace) { | ||||||||
2450 | for (i = 0; i < PyArray_NDIM(mit->subspace); i++) { | ||||||||
2451 | mit->dimensions[mit->nd_fancy + i] = PyArray_DIM(mit->subspace, i); | ||||||||
2452 | } | ||||||||
2453 | } | ||||||||
2454 | |||||||||
2455 | return 0; | ||||||||
2456 | |||||||||
2457 | broadcast_error: ; // Declarations cannot follow labels, add empty statement. | ||||||||
2458 | /* | ||||||||
2459 | * Attempt to set a meaningful exception. Could also find out | ||||||||
2460 | * if a boolean index was converted. | ||||||||
2461 | */ | ||||||||
2462 | PyObject *errmsg = PyUnicode_FromString(""); | ||||||||
2463 | if (errmsg == NULL((void*)0)) { | ||||||||
2464 | return -1; | ||||||||
2465 | } | ||||||||
2466 | for (i = 0; i < index_num; i++) { | ||||||||
2467 | if (!(indices[i].type & HAS_FANCY)) { | ||||||||
2468 | continue; | ||||||||
2469 | } | ||||||||
2470 | |||||||||
2471 | int ndim = PyArray_NDIM((PyArrayObject *)indices[i].object); | ||||||||
2472 | npy_intp *shape = PyArray_SHAPE((PyArrayObject *)indices[i].object); | ||||||||
2473 | PyObject *tmp = convert_shape_to_string(ndim, shape, " "); | ||||||||
2474 | if (tmp == NULL((void*)0)) { | ||||||||
2475 | Py_DECREF(errmsg)_Py_DECREF(((PyObject*)(errmsg))); | ||||||||
2476 | return -1; | ||||||||
2477 | } | ||||||||
2478 | |||||||||
2479 | Py_SETREF(errmsg, PyUnicode_Concat(errmsg, tmp))do { PyObject *_py_tmp = ((PyObject*)(errmsg)); (errmsg) = (PyUnicode_Concat (errmsg, tmp)); _Py_DECREF(((PyObject*)(_py_tmp))); } while ( 0); | ||||||||
2480 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | ||||||||
2481 | if (errmsg == NULL((void*)0)) { | ||||||||
2482 | return -1; | ||||||||
2483 | } | ||||||||
2484 | } | ||||||||
2485 | |||||||||
2486 | PyErr_Format(PyExc_IndexError, | ||||||||
2487 | "shape mismatch: indexing arrays could not " | ||||||||
2488 | "be broadcast together with shapes %S", errmsg); | ||||||||
2489 | Py_DECREF(errmsg)_Py_DECREF(((PyObject*)(errmsg))); | ||||||||
2490 | return -1; | ||||||||
2491 | } | ||||||||
2492 | |||||||||
2493 | |||||||||
2494 | /* | ||||||||
2495 | * Check whether the fancy indices are out of bounds. | ||||||||
2496 | * Returns 0 on success and -1 on failure. | ||||||||
2497 | * (Gets operands from the outer iterator, but iterates them independently) | ||||||||
2498 | */ | ||||||||
2499 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||
2500 | PyArray_MapIterCheckIndices(PyArrayMapIterObject *mit) | ||||||||
2501 | { | ||||||||
2502 | PyArrayObject *op; | ||||||||
2503 | NpyIter *op_iter; | ||||||||
2504 | NpyIter_IterNextFunc *op_iternext; | ||||||||
2505 | npy_intp outer_dim, indval; | ||||||||
2506 | int outer_axis; | ||||||||
2507 | npy_intp itersize, *iterstride; | ||||||||
2508 | char **iterptr; | ||||||||
2509 | PyArray_Descr *intp_type; | ||||||||
2510 | int i; | ||||||||
2511 | NPY_BEGIN_THREADS_DEFPyThreadState *_save=((void*)0);; | ||||||||
2512 | |||||||||
2513 | if (NpyIter_GetIterSize(mit->outer) == 0) { | ||||||||
2514 | /* | ||||||||
2515 | * When the outer iteration is empty, the indices broadcast to an | ||||||||
2516 | * empty shape, and in this case we do not check if there are out | ||||||||
2517 | * of bounds indices. | ||||||||
2518 | * The code below does use the indices without broadcasting since | ||||||||
2519 | * broadcasting only repeats values. | ||||||||
2520 | */ | ||||||||
2521 | return 0; | ||||||||
2522 | } | ||||||||
2523 | |||||||||
2524 | intp_type = PyArray_DescrFromType(NPY_INTPNPY_LONG); | ||||||||
2525 | |||||||||
2526 | NPY_BEGIN_THREADSdo {_save = PyEval_SaveThread();} while (0);; | ||||||||
2527 | |||||||||
2528 | for (i=0; i < mit->numiter; i++) { | ||||||||
2529 | op = NpyIter_GetOperandArray(mit->outer)[i]; | ||||||||
2530 | |||||||||
2531 | outer_dim = mit->fancy_dims[i]; | ||||||||
2532 | outer_axis = mit->iteraxes[i]; | ||||||||
2533 | |||||||||
2534 | /* See if it is possible to just trivially iterate the array */ | ||||||||
2535 | if (PyArray_TRIVIALLY_ITERABLE(op)( PyArray_NDIM(op) <= 1 || PyArray_CHKFLAGS(op, 0x0001) || PyArray_CHKFLAGS(op, 0x0002) ) && | ||||||||
2536 | /* Check if the type is equivalent to INTP */ | ||||||||
2537 | PyArray_ITEMSIZE(op) == sizeof(npy_intp) && | ||||||||
2538 | PyArray_DESCR(op)->kind == 'i' && | ||||||||
2539 | IsUintAligned(op) && | ||||||||
2540 | PyDataType_ISNOTSWAPPED(PyArray_DESCR(op))((((PyArray_Descr *)(PyArray_DESCR(op)))->byteorder) != '>' )) { | ||||||||
2541 | char *data; | ||||||||
2542 | npy_intp stride; | ||||||||
2543 | /* release GIL if it was taken by nditer below */ | ||||||||
2544 | if (_save == NULL((void*)0)) { | ||||||||
2545 | NPY_BEGIN_THREADSdo {_save = PyEval_SaveThread();} while (0);; | ||||||||
2546 | } | ||||||||
2547 | |||||||||
2548 | PyArray_PREPARE_TRIVIAL_ITERATION(op, itersize, data, stride)itersize = PyArray_MultiplyList(PyArray_DIMS(op), PyArray_NDIM (op)); data = PyArray_BYTES(op); stride = ((PyArray_NDIM(op) == 0) ? 0 : ((PyArray_NDIM(op) == 1) ? PyArray_STRIDE(op, 0) : PyArray_ITEMSIZE (op)));; | ||||||||
2549 | |||||||||
2550 | while (itersize--) { | ||||||||
2551 | indval = *((npy_intp*)data); | ||||||||
2552 | if (check_and_adjust_index(&indval, | ||||||||
2553 | outer_dim, outer_axis, _save) < 0) { | ||||||||
2554 | Py_DECREF(intp_type)_Py_DECREF(((PyObject*)(intp_type))); | ||||||||
2555 | goto indexing_error; | ||||||||
2556 | } | ||||||||
2557 | data += stride; | ||||||||
2558 | } | ||||||||
2559 | /* GIL retake at end of function or if nditer path required */ | ||||||||
2560 | continue; | ||||||||
2561 | } | ||||||||
2562 | |||||||||
2563 | /* Use NpyIter if the trivial iteration is not possible */ | ||||||||
2564 | NPY_END_THREADSdo { if (_save) { PyEval_RestoreThread(_save); _save = ((void *)0);} } while (0);; | ||||||||
2565 | op_iter = NpyIter_New(op, | ||||||||
2566 | NPY_ITER_BUFFERED0x00000200 | NPY_ITER_NBO0x00080000 | NPY_ITER_ALIGNED0x00100000 | | ||||||||
2567 | NPY_ITER_EXTERNAL_LOOP0x00000008 | NPY_ITER_GROWINNER0x00000400 | | ||||||||
2568 | NPY_ITER_READONLY0x00020000 | NPY_ITER_ZEROSIZE_OK0x00000040, | ||||||||
2569 | NPY_KEEPORDER, NPY_SAME_KIND_CASTING, intp_type); | ||||||||
2570 | |||||||||
2571 | if (op_iter == NULL((void*)0)) { | ||||||||
2572 | Py_DECREF(intp_type)_Py_DECREF(((PyObject*)(intp_type))); | ||||||||
2573 | return -1; | ||||||||
2574 | } | ||||||||
2575 | if (NpyIter_GetIterSize(op_iter) == 0) { | ||||||||
2576 | NpyIter_Deallocate(op_iter); | ||||||||
2577 | continue; | ||||||||
2578 | } | ||||||||
2579 | |||||||||
2580 | op_iternext = NpyIter_GetIterNext(op_iter, NULL((void*)0)); | ||||||||
2581 | if (op_iternext == NULL((void*)0)) { | ||||||||
2582 | Py_DECREF(intp_type)_Py_DECREF(((PyObject*)(intp_type))); | ||||||||
2583 | NpyIter_Deallocate(op_iter); | ||||||||
2584 | return -1; | ||||||||
2585 | } | ||||||||
2586 | |||||||||
2587 | NPY_BEGIN_THREADS_NDITER(op_iter)do { if (!NpyIter_IterationNeedsAPI(op_iter)) { do { if ((NpyIter_GetIterSize (op_iter)) > 500) { _save = PyEval_SaveThread();} } while ( 0);; } } while(0); | ||||||||
2588 | iterptr = NpyIter_GetDataPtrArray(op_iter); | ||||||||
2589 | iterstride = NpyIter_GetInnerStrideArray(op_iter); | ||||||||
2590 | do { | ||||||||
2591 | itersize = *NpyIter_GetInnerLoopSizePtr(op_iter); | ||||||||
2592 | while (itersize--) { | ||||||||
2593 | indval = *((npy_intp*)*iterptr); | ||||||||
2594 | if (check_and_adjust_index(&indval, | ||||||||
2595 | outer_dim, outer_axis, _save) < 0) { | ||||||||
2596 | Py_DECREF(intp_type)_Py_DECREF(((PyObject*)(intp_type))); | ||||||||
2597 | NpyIter_Deallocate(op_iter); | ||||||||
2598 | goto indexing_error; | ||||||||
2599 | } | ||||||||
2600 | *iterptr += *iterstride; | ||||||||
2601 | } | ||||||||
2602 | } while (op_iternext(op_iter)); | ||||||||
2603 | |||||||||
2604 | NPY_END_THREADSdo { if (_save) { PyEval_RestoreThread(_save); _save = ((void *)0);} } while (0);; | ||||||||
2605 | NpyIter_Deallocate(op_iter); | ||||||||
2606 | } | ||||||||
2607 | |||||||||
2608 | NPY_END_THREADSdo { if (_save) { PyEval_RestoreThread(_save); _save = ((void *)0);} } while (0);; | ||||||||
2609 | Py_DECREF(intp_type)_Py_DECREF(((PyObject*)(intp_type))); | ||||||||
2610 | return 0; | ||||||||
2611 | |||||||||
2612 | indexing_error: | ||||||||
2613 | |||||||||
2614 | if (mit->size == 0) { | ||||||||
2615 | PyObject *err_type = NULL((void*)0), *err_value = NULL((void*)0), *err_traceback = NULL((void*)0); | ||||||||
2616 | PyErr_Fetch(&err_type, &err_value, &err_traceback); | ||||||||
2617 | /* 2020-05-27, NumPy 1.20 */ | ||||||||
2618 | if (DEPRECATE(PyErr_WarnEx(PyExc_DeprecationWarning,"Out of bound index found. This was previously ignored " "when the indexing result contained no elements. " "In the future the index error will be raised. This error " "occurs either due to an empty slice, or if an array has zero " "elements even before indexing.\n" "(Use `warnings.simplefilter('error')` to turn this " "DeprecationWarning into an error and get more details on " "the invalid index.)" ,1) | ||||||||
2619 | "Out of bound index found. This was previously ignored "PyErr_WarnEx(PyExc_DeprecationWarning,"Out of bound index found. This was previously ignored " "when the indexing result contained no elements. " "In the future the index error will be raised. This error " "occurs either due to an empty slice, or if an array has zero " "elements even before indexing.\n" "(Use `warnings.simplefilter('error')` to turn this " "DeprecationWarning into an error and get more details on " "the invalid index.)" ,1) | ||||||||
2620 | "when the indexing result contained no elements. "PyErr_WarnEx(PyExc_DeprecationWarning,"Out of bound index found. This was previously ignored " "when the indexing result contained no elements. " "In the future the index error will be raised. This error " "occurs either due to an empty slice, or if an array has zero " "elements even before indexing.\n" "(Use `warnings.simplefilter('error')` to turn this " "DeprecationWarning into an error and get more details on " "the invalid index.)" ,1) | ||||||||
2621 | "In the future the index error will be raised. This error "PyErr_WarnEx(PyExc_DeprecationWarning,"Out of bound index found. This was previously ignored " "when the indexing result contained no elements. " "In the future the index error will be raised. This error " "occurs either due to an empty slice, or if an array has zero " "elements even before indexing.\n" "(Use `warnings.simplefilter('error')` to turn this " "DeprecationWarning into an error and get more details on " "the invalid index.)" ,1) | ||||||||
2622 | "occurs either due to an empty slice, or if an array has zero "PyErr_WarnEx(PyExc_DeprecationWarning,"Out of bound index found. This was previously ignored " "when the indexing result contained no elements. " "In the future the index error will be raised. This error " "occurs either due to an empty slice, or if an array has zero " "elements even before indexing.\n" "(Use `warnings.simplefilter('error')` to turn this " "DeprecationWarning into an error and get more details on " "the invalid index.)" ,1) | ||||||||
2623 | "elements even before indexing.\n"PyErr_WarnEx(PyExc_DeprecationWarning,"Out of bound index found. This was previously ignored " "when the indexing result contained no elements. " "In the future the index error will be raised. This error " "occurs either due to an empty slice, or if an array has zero " "elements even before indexing.\n" "(Use `warnings.simplefilter('error')` to turn this " "DeprecationWarning into an error and get more details on " "the invalid index.)" ,1) | ||||||||
2624 | "(Use `warnings.simplefilter('error')` to turn this "PyErr_WarnEx(PyExc_DeprecationWarning,"Out of bound index found. This was previously ignored " "when the indexing result contained no elements. " "In the future the index error will be raised. This error " "occurs either due to an empty slice, or if an array has zero " "elements even before indexing.\n" "(Use `warnings.simplefilter('error')` to turn this " "DeprecationWarning into an error and get more details on " "the invalid index.)" ,1) | ||||||||
2625 | "DeprecationWarning into an error and get more details on "PyErr_WarnEx(PyExc_DeprecationWarning,"Out of bound index found. This was previously ignored " "when the indexing result contained no elements. " "In the future the index error will be raised. This error " "occurs either due to an empty slice, or if an array has zero " "elements even before indexing.\n" "(Use `warnings.simplefilter('error')` to turn this " "DeprecationWarning into an error and get more details on " "the invalid index.)" ,1) | ||||||||
2626 | "the invalid index.)")PyErr_WarnEx(PyExc_DeprecationWarning,"Out of bound index found. This was previously ignored " "when the indexing result contained no elements. " "In the future the index error will be raised. This error " "occurs either due to an empty slice, or if an array has zero " "elements even before indexing.\n" "(Use `warnings.simplefilter('error')` to turn this " "DeprecationWarning into an error and get more details on " "the invalid index.)" ,1) < 0) { | ||||||||
2627 | npy_PyErr_ChainExceptions(err_type, err_value, err_traceback); | ||||||||
2628 | return -1; | ||||||||
2629 | } | ||||||||
2630 | Py_DECREF(err_type)_Py_DECREF(((PyObject*)(err_type))); | ||||||||
2631 | Py_DECREF(err_value)_Py_DECREF(((PyObject*)(err_value))); | ||||||||
2632 | Py_XDECREF(err_traceback)_Py_XDECREF(((PyObject*)(err_traceback))); | ||||||||
2633 | return 0; | ||||||||
2634 | } | ||||||||
2635 | |||||||||
2636 | return -1; | ||||||||
2637 | } | ||||||||
2638 | |||||||||
2639 | |||||||||
2640 | /* | ||||||||
2641 | * Create new mapiter. | ||||||||
2642 | * | ||||||||
2643 | * NOTE: The outer iteration (and subspace if requested buffered) is | ||||||||
2644 | * created with DELAY_BUFALLOC. It must be reset before usage! | ||||||||
2645 | * | ||||||||
2646 | * @param Index information filled by prepare_index. | ||||||||
2647 | * @param Number of indices (gotten through prepare_index). | ||||||||
2648 | * @param Kind of index (gotten through preprare_index). | ||||||||
2649 | * @param NpyIter flags for an extra array. If 0 assume that there is no | ||||||||
2650 | * extra operand. NPY_ITER_ALLOCATE can make sense here. | ||||||||
2651 | * @param Array being indexed | ||||||||
2652 | * @param subspace (result of getting view for the indices) | ||||||||
2653 | * @param Subspace iterator flags can be used to enable buffering. | ||||||||
2654 | * NOTE: When no subspace is necessary, the extra operand will | ||||||||
2655 | * always be buffered! Buffering the subspace when not | ||||||||
2656 | * necessary is very slow when the subspace is small. | ||||||||
2657 | * @param Subspace operand flags (should just be 0 normally) | ||||||||
2658 | * @param Operand iteration flags for the extra operand, this must not be | ||||||||
2659 | * 0 if an extra operand should be used, otherwise it must be 0. | ||||||||
2660 | * Should be at least READONLY, WRITEONLY or READWRITE. | ||||||||
2661 | * @param Extra operand. For getmap, this would be the result, for setmap | ||||||||
2662 | * this would be the arrays to get from. | ||||||||
2663 | * Can be NULL, and will be allocated in that case. However, | ||||||||
2664 | * it matches the mapiter iteration, so you have to call | ||||||||
2665 | * MapIterSwapAxes(mit, &extra_op, 1) on it. | ||||||||
2666 | * The operand has no effect on the shape. | ||||||||
2667 | * @param Dtype for the extra operand, borrows the reference and must not | ||||||||
2668 | * be NULL (if extra_op_flags is not 0). | ||||||||
2669 | * | ||||||||
2670 | * @return A new MapIter (PyObject *) or NULL. | ||||||||
2671 | */ | ||||||||
2672 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||
2673 | PyArray_MapIterNew(npy_index_info *indices , int index_num, int index_type, | ||||||||
2674 | int ndim, int fancy_ndim, | ||||||||
2675 | PyArrayObject *arr, PyArrayObject *subspace, | ||||||||
2676 | npy_uint32 subspace_iter_flags, npy_uint32 subspace_flags, | ||||||||
2677 | npy_uint32 extra_op_flags, PyArrayObject *extra_op, | ||||||||
2678 | PyArray_Descr *extra_op_dtype) | ||||||||
2679 | { | ||||||||
2680 | /* For shape reporting on error */ | ||||||||
2681 | PyArrayObject *original_extra_op = extra_op; | ||||||||
2682 | |||||||||
2683 | /* NOTE: MAXARGS is the actual limit (2*NPY_MAXDIMS is index number one) */ | ||||||||
2684 | PyArrayObject *index_arrays[NPY_MAXDIMS32]; | ||||||||
2685 | PyArray_Descr *intp_descr; | ||||||||
2686 | PyArray_Descr *dtypes[NPY_MAXDIMS32]; /* borrowed references */ | ||||||||
2687 | |||||||||
2688 | npy_uint32 op_flags[NPY_MAXDIMS32]; | ||||||||
2689 | npy_uint32 outer_flags; | ||||||||
2690 | |||||||||
2691 | PyArrayMapIterObject *mit; | ||||||||
2692 | |||||||||
2693 | int single_op_axis[NPY_MAXDIMS32]; | ||||||||
2694 | int *op_axes[NPY_MAXDIMS32] = {NULL((void*)0)}; | ||||||||
2695 | int i, j, dummy_array = 0; | ||||||||
2696 | int nops; | ||||||||
2697 | int uses_subspace; | ||||||||
2698 | |||||||||
2699 | intp_descr = PyArray_DescrFromType(NPY_INTPNPY_LONG); | ||||||||
2700 | if (intp_descr == NULL((void*)0)) { | ||||||||
2701 | return NULL((void*)0); | ||||||||
2702 | } | ||||||||
2703 | |||||||||
2704 | /* create new MapIter object */ | ||||||||
2705 | mit = (PyArrayMapIterObject *)PyArray_mallocPyMem_RawMalloc(sizeof(PyArrayMapIterObject)); | ||||||||
2706 | if (mit == NULL((void*)0)) { | ||||||||
2707 | Py_DECREF(intp_descr)_Py_DECREF(((PyObject*)(intp_descr))); | ||||||||
2708 | return NULL((void*)0); | ||||||||
2709 | } | ||||||||
2710 | /* set all attributes of mapiter to zero */ | ||||||||
2711 | memset(mit, 0, sizeof(PyArrayMapIterObject)); | ||||||||
2712 | PyObject_Init((PyObject *)mit, &PyArrayMapIter_Type); | ||||||||
2713 | |||||||||
2714 | Py_INCREF(arr)_Py_INCREF(((PyObject*)(arr))); | ||||||||
2715 | mit->array = arr; | ||||||||
2716 | Py_XINCREF(subspace)_Py_XINCREF(((PyObject*)(subspace))); | ||||||||
2717 | mit->subspace = subspace; | ||||||||
2718 | |||||||||
2719 | /* | ||||||||
2720 | * The subspace, the part of the array which is not indexed by | ||||||||
2721 | * arrays, needs to be iterated when the size of the subspace | ||||||||
2722 | * is larger than 1. If it is one, it has only an effect on the | ||||||||
2723 | * result shape. (Optimizes for example np.newaxis usage) | ||||||||
2724 | */ | ||||||||
2725 | if ((subspace == NULL((void*)0)) || PyArray_SIZE(subspace)PyArray_MultiplyList(PyArray_DIMS(subspace), PyArray_NDIM(subspace )) == 1) { | ||||||||
2726 | uses_subspace = 0; | ||||||||
2727 | } | ||||||||
2728 | else { | ||||||||
2729 | uses_subspace = 1; | ||||||||
2730 | } | ||||||||
2731 | |||||||||
2732 | /* Fill basic information about the mapiter */ | ||||||||
2733 | mit->nd = ndim; | ||||||||
2734 | mit->nd_fancy = fancy_ndim; | ||||||||
2735 | if (mapiter_fill_info(mit, indices, index_num, arr) < 0) { | ||||||||
2736 | Py_DECREF(mit)_Py_DECREF(((PyObject*)(mit))); | ||||||||
2737 | Py_DECREF(intp_descr)_Py_DECREF(((PyObject*)(intp_descr))); | ||||||||
2738 | return NULL((void*)0); | ||||||||
2739 | } | ||||||||
2740 | |||||||||
2741 | /* | ||||||||
2742 | * Set iteration information of the indexing arrays. | ||||||||
2743 | */ | ||||||||
2744 | for (i=0; i < index_num; i++) { | ||||||||
2745 | if (indices[i].type & HAS_FANCY) { | ||||||||
2746 | index_arrays[mit->numiter] = (PyArrayObject *)indices[i].object; | ||||||||
2747 | dtypes[mit->numiter] = intp_descr; | ||||||||
2748 | |||||||||
2749 | op_flags[mit->numiter] = (NPY_ITER_NBO0x00080000 | | ||||||||
2750 | NPY_ITER_ALIGNED0x00100000 | | ||||||||
2751 | NPY_ITER_READONLY0x00020000); | ||||||||
2752 | mit->numiter += 1; | ||||||||
2753 | } | ||||||||
2754 | } | ||||||||
2755 | |||||||||
2756 | if (mit->numiter == 0) { | ||||||||
2757 | /* | ||||||||
2758 | * For MapIterArray, it is possible that there is no fancy index. | ||||||||
2759 | * to support this case, add a dummy iterator. | ||||||||
2760 | * Since it is 0-d its transpose, etc. does not matter. | ||||||||
2761 | */ | ||||||||
2762 | |||||||||
2763 | /* signal necessity to decref... */ | ||||||||
2764 | dummy_array = 1; | ||||||||
2765 | |||||||||
2766 | index_arrays[0] = (PyArrayObject *)PyArray_Zeros(0, NULL((void*)0), | ||||||||
2767 | PyArray_DescrFromType(NPY_INTPNPY_LONG), 0); | ||||||||
2768 | if (index_arrays[0] == NULL((void*)0)) { | ||||||||
2769 | Py_DECREF(mit)_Py_DECREF(((PyObject*)(mit))); | ||||||||
2770 | Py_DECREF(intp_descr)_Py_DECREF(((PyObject*)(intp_descr))); | ||||||||
2771 | return NULL((void*)0); | ||||||||
2772 | } | ||||||||
2773 | dtypes[0] = intp_descr; | ||||||||
2774 | op_flags[0] = NPY_ITER_NBO0x00080000 | NPY_ITER_ALIGNED0x00100000 | NPY_ITER_READONLY0x00020000; | ||||||||
2775 | |||||||||
2776 | mit->fancy_dims[0] = 1; | ||||||||
2777 | mit->numiter = 1; | ||||||||
2778 | } | ||||||||
2779 | |||||||||
2780 | /* | ||||||||
2781 | * Now there are two general cases how extra_op is used: | ||||||||
2782 | * 1. No subspace iteration is necessary, so the extra_op can | ||||||||
2783 | * be included into the index iterator (it will be buffered) | ||||||||
2784 | * 2. Subspace iteration is necessary, so the extra op is iterated | ||||||||
2785 | * independently, and the iteration order is fixed at C (could | ||||||||
2786 | * also use Fortran order if the array is Fortran order). | ||||||||
2787 | * In this case the subspace iterator is not buffered. | ||||||||
2788 | * | ||||||||
2789 | * If subspace iteration is necessary and an extra_op was given, | ||||||||
2790 | * it may also be necessary to transpose the extra_op (or signal | ||||||||
2791 | * the transposing to the advanced iterator). | ||||||||
2792 | */ | ||||||||
2793 | |||||||||
2794 | if (extra_op != NULL((void*)0)) { | ||||||||
2795 | /* | ||||||||
2796 | * If we have an extra_op given, need to prepare it. | ||||||||
2797 | * 1. Subclasses might mess with the shape, so need a baseclass | ||||||||
2798 | * 2. Need to make sure the shape is compatible | ||||||||
2799 | * 3. May need to remove leading 1s and transpose dimensions. | ||||||||
2800 | * Normal assignments allows broadcasting away leading 1s, but | ||||||||
2801 | * the transposing code does not like this. | ||||||||
2802 | */ | ||||||||
2803 | if (!PyArray_CheckExact(extra_op)(((PyObject*)(extra_op))->ob_type == &PyArray_Type)) { | ||||||||
2804 | extra_op = (PyArrayObject *)PyArray_View(extra_op, NULL((void*)0), | ||||||||
2805 | &PyArray_Type); | ||||||||
2806 | if (extra_op == NULL((void*)0)) { | ||||||||
2807 | goto fail; | ||||||||
2808 | } | ||||||||
2809 | } | ||||||||
2810 | else { | ||||||||
2811 | Py_INCREF(extra_op)_Py_INCREF(((PyObject*)(extra_op))); | ||||||||
2812 | } | ||||||||
2813 | |||||||||
2814 | if (PyArray_NDIM(extra_op) > mit->nd) { | ||||||||
2815 | /* | ||||||||
2816 | * Usual assignments allows removal of leading one dimensions. | ||||||||
2817 | * (or equivalently adding of one dimensions to the array being | ||||||||
2818 | * assigned to). To implement this, reshape the array. | ||||||||
2819 | */ | ||||||||
2820 | PyArrayObject *tmp_arr; | ||||||||
2821 | PyArray_Dims permute; | ||||||||
2822 | |||||||||
2823 | permute.len = mit->nd; | ||||||||
2824 | permute.ptr = &PyArray_DIMS(extra_op)[ | ||||||||
2825 | PyArray_NDIM(extra_op) - mit->nd]; | ||||||||
2826 | tmp_arr = (PyArrayObject*)PyArray_Newshape(extra_op, &permute, | ||||||||
2827 | NPY_CORDER); | ||||||||
2828 | if (tmp_arr == NULL((void*)0)) { | ||||||||
2829 | goto broadcast_error; | ||||||||
2830 | } | ||||||||
2831 | Py_DECREF(extra_op)_Py_DECREF(((PyObject*)(extra_op))); | ||||||||
2832 | extra_op = tmp_arr; | ||||||||
2833 | } | ||||||||
2834 | |||||||||
2835 | /* | ||||||||
2836 | * If dimensions need to be prepended (and no swapaxis is needed), | ||||||||
2837 | * use op_axes after extra_op is allocated for sure. | ||||||||
2838 | */ | ||||||||
2839 | if (mit->consec) { | ||||||||
2840 | PyArray_MapIterSwapAxes(mit, &extra_op, 0); | ||||||||
2841 | if (extra_op == NULL((void*)0)) { | ||||||||
2842 | goto fail; | ||||||||
2843 | } | ||||||||
2844 | } | ||||||||
2845 | |||||||||
2846 | if (subspace && !uses_subspace) { | ||||||||
2847 | /* | ||||||||
2848 | * We are not using the subspace, so its size is 1. | ||||||||
2849 | * All dimensions of the extra_op corresponding to the | ||||||||
2850 | * subspace must be equal to 1. | ||||||||
2851 | */ | ||||||||
2852 | if (PyArray_NDIM(subspace) <= PyArray_NDIM(extra_op)) { | ||||||||
2853 | j = PyArray_NDIM(subspace); | ||||||||
2854 | } | ||||||||
2855 | else { | ||||||||
2856 | j = PyArray_NDIM(extra_op); | ||||||||
2857 | } | ||||||||
2858 | for (i = 1; i < j + 1; i++) { | ||||||||
2859 | if (PyArray_DIM(extra_op, PyArray_NDIM(extra_op) - i) != 1) { | ||||||||
2860 | goto broadcast_error; | ||||||||
2861 | } | ||||||||
2862 | } | ||||||||
2863 | } | ||||||||
2864 | } | ||||||||
2865 | |||||||||
2866 | /* | ||||||||
2867 | * If subspace is not NULL, NpyIter cannot allocate extra_op for us. | ||||||||
2868 | * This is a bit of a kludge. A dummy iterator is created to find | ||||||||
2869 | * the correct output shape and stride permutation. | ||||||||
2870 | * TODO: This can at least partially be replaced, since the shape | ||||||||
2871 | * is found for broadcasting errors. | ||||||||
2872 | */ | ||||||||
2873 | else if (extra_op_flags && (subspace != NULL((void*)0))) { | ||||||||
2874 | npy_uint32 tmp_op_flags[NPY_MAXDIMS32]; | ||||||||
2875 | |||||||||
2876 | NpyIter *tmp_iter; | ||||||||
2877 | npy_intp stride; | ||||||||
2878 | npy_intp strides[NPY_MAXDIMS32]; | ||||||||
2879 | npy_stride_sort_item strideperm[NPY_MAXDIMS32]; | ||||||||
2880 | |||||||||
2881 | for (i=0; i < mit->numiter; i++) { | ||||||||
2882 | tmp_op_flags[i] = NPY_ITER_READONLY0x00020000; | ||||||||
2883 | } | ||||||||
2884 | |||||||||
2885 | Py_INCREF(extra_op_dtype)_Py_INCREF(((PyObject*)(extra_op_dtype))); | ||||||||
2886 | mit->extra_op_dtype = extra_op_dtype; | ||||||||
2887 | |||||||||
2888 | if (PyArray_SIZE(subspace)PyArray_MultiplyList(PyArray_DIMS(subspace), PyArray_NDIM(subspace )) == 1) { | ||||||||
2889 | /* Create an iterator, just to broadcast the arrays?! */ | ||||||||
2890 | tmp_iter = NpyIter_MultiNew(mit->numiter, index_arrays, | ||||||||
2891 | NPY_ITER_ZEROSIZE_OK0x00000040 | | ||||||||
2892 | NPY_ITER_REFS_OK0x00000020 | | ||||||||
2893 | NPY_ITER_MULTI_INDEX0x00000004 | | ||||||||
2894 | NPY_ITER_DONT_NEGATE_STRIDES0x00001000, | ||||||||
2895 | NPY_KEEPORDER, | ||||||||
2896 | NPY_UNSAFE_CASTING, | ||||||||
2897 | tmp_op_flags, NULL((void*)0)); | ||||||||
2898 | if (tmp_iter == NULL((void*)0)) { | ||||||||
2899 | goto fail; | ||||||||
2900 | } | ||||||||
2901 | |||||||||
2902 | /* | ||||||||
2903 | * nditer allows itemsize with npy_intp type, so it works | ||||||||
2904 | * here, but it would *not* work directly, since elsize | ||||||||
2905 | * is limited to int. | ||||||||
2906 | */ | ||||||||
2907 | if (!NpyIter_CreateCompatibleStrides(tmp_iter, | ||||||||
2908 | extra_op_dtype->elsize * PyArray_SIZE(subspace)PyArray_MultiplyList(PyArray_DIMS(subspace), PyArray_NDIM(subspace )), | ||||||||
2909 | strides)) { | ||||||||
2910 | PyErr_SetString(PyExc_ValueError, | ||||||||
2911 | "internal error: failed to find output array strides"); | ||||||||
2912 | goto fail; | ||||||||
2913 | } | ||||||||
2914 | NpyIter_Deallocate(tmp_iter); | ||||||||
2915 | } | ||||||||
2916 | else { | ||||||||
2917 | /* Just use C-order strides (TODO: allow also F-order) */ | ||||||||
2918 | stride = extra_op_dtype->elsize * PyArray_SIZE(subspace)PyArray_MultiplyList(PyArray_DIMS(subspace), PyArray_NDIM(subspace )); | ||||||||
2919 | for (i=mit->nd_fancy - 1; i >= 0; i--) { | ||||||||
2920 | strides[i] = stride; | ||||||||
2921 | stride *= mit->dimensions[i]; | ||||||||
2922 | } | ||||||||
2923 | } | ||||||||
2924 | |||||||||
2925 | /* shape is set, and strides is set up to mit->nd, set rest */ | ||||||||
2926 | PyArray_CreateSortedStridePerm(PyArray_NDIM(subspace), | ||||||||
2927 | PyArray_STRIDES(subspace), strideperm); | ||||||||
2928 | stride = extra_op_dtype->elsize; | ||||||||
2929 | for (i=PyArray_NDIM(subspace) - 1; i >= 0; i--) { | ||||||||
2930 | strides[mit->nd_fancy + strideperm[i].perm] = stride; | ||||||||
2931 | stride *= PyArray_DIM(subspace, (int)strideperm[i].perm); | ||||||||
2932 | } | ||||||||
2933 | |||||||||
2934 | /* | ||||||||
2935 | * Allocate new array. Note: Always base class, because | ||||||||
2936 | * subclasses might mess with the shape. | ||||||||
2937 | */ | ||||||||
2938 | Py_INCREF(extra_op_dtype)_Py_INCREF(((PyObject*)(extra_op_dtype))); | ||||||||
2939 | extra_op = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, | ||||||||
2940 | extra_op_dtype, | ||||||||
2941 | mit->nd_fancy + PyArray_NDIM(subspace), | ||||||||
2942 | mit->dimensions, strides, | ||||||||
2943 | NULL((void*)0), 0, NULL((void*)0)); | ||||||||
2944 | if (extra_op == NULL((void*)0)) { | ||||||||
2945 | goto fail; | ||||||||
2946 | } | ||||||||
2947 | } | ||||||||
2948 | |||||||||
2949 | /* | ||||||||
2950 | * The extra op is now either allocated, can be allocated by | ||||||||
2951 | * NpyIter (no subspace) or is not used at all. | ||||||||
2952 | * | ||||||||
2953 | * Need to set the axis remapping for the extra_op. This needs | ||||||||
2954 | * to cause ignoring of subspace dimensions and prepending -1 | ||||||||
2955 | * for broadcasting. | ||||||||
2956 | */ | ||||||||
2957 | if (extra_op) { | ||||||||
2958 | for (j=0; j < mit->nd - PyArray_NDIM(extra_op); j++) { | ||||||||
2959 | single_op_axis[j] = -1; | ||||||||
2960 | } | ||||||||
2961 | for (i=0; i < PyArray_NDIM(extra_op); i++) { | ||||||||
2962 | /* (fills subspace dimensions too, but they are not unused) */ | ||||||||
2963 | single_op_axis[j++] = i; | ||||||||
2964 | } | ||||||||
2965 | } | ||||||||
2966 | |||||||||
2967 | /* | ||||||||
2968 | * NOTE: If for some reason someone wishes to use REDUCE_OK, be | ||||||||
2969 | * careful and fix the error message replacement at the end. | ||||||||
2970 | */ | ||||||||
2971 | outer_flags = NPY_ITER_ZEROSIZE_OK0x00000040 | | ||||||||
2972 | NPY_ITER_REFS_OK0x00000020 | | ||||||||
2973 | NPY_ITER_BUFFERED0x00000200 | | ||||||||
2974 | NPY_ITER_DELAY_BUFALLOC0x00000800 | | ||||||||
2975 | NPY_ITER_GROWINNER0x00000400; | ||||||||
2976 | |||||||||
2977 | /* | ||||||||
2978 | * For a single 1-d operand, guarantee iteration order | ||||||||
2979 | * (scipy used this). Note that subspace may be used. | ||||||||
2980 | */ | ||||||||
2981 | if ((mit->numiter == 1) && (PyArray_NDIM(index_arrays[0]) == 1)) { | ||||||||
2982 | outer_flags |= NPY_ITER_DONT_NEGATE_STRIDES0x00001000; | ||||||||
2983 | } | ||||||||
2984 | |||||||||
2985 | /* If external array is iterated, and no subspace is needed */ | ||||||||
2986 | nops = mit->numiter; | ||||||||
2987 | if (extra_op_flags && !uses_subspace) { | ||||||||
2988 | /* | ||||||||
2989 | * NOTE: This small limitation should practically not matter. | ||||||||
2990 | * (replaces npyiter error) | ||||||||
2991 | */ | ||||||||
2992 | if (mit->numiter > NPY_MAXDIMS32 - 1) { | ||||||||
2993 | PyErr_Format(PyExc_IndexError, | ||||||||
2994 | "when no subspace is given, the number of index " | ||||||||
2995 | "arrays cannot be above %d, but %d index arrays found", | ||||||||
2996 | NPY_MAXDIMS32 - 1, mit->numiter); | ||||||||
2997 | goto fail; | ||||||||
2998 | } | ||||||||
2999 | |||||||||
3000 | nops += 1; | ||||||||
3001 | index_arrays[mit->numiter] = extra_op; | ||||||||
3002 | |||||||||
3003 | dtypes[mit->numiter] = extra_op_dtype; | ||||||||
3004 | op_flags[mit->numiter] = (extra_op_flags | | ||||||||
3005 | NPY_ITER_ALLOCATE0x01000000 | | ||||||||
3006 | NPY_ITER_NO_SUBTYPE0x02000000); | ||||||||
3007 | |||||||||
3008 | if (extra_op) { | ||||||||
3009 | /* Use the axis remapping */ | ||||||||
3010 | op_axes[mit->numiter] = single_op_axis; | ||||||||
3011 | mit->outer = NpyIter_AdvancedNew(nops, index_arrays, outer_flags, | ||||||||
3012 | NPY_KEEPORDER, NPY_UNSAFE_CASTING, op_flags, dtypes, | ||||||||
3013 | mit->nd_fancy, op_axes, mit->dimensions, 0); | ||||||||
3014 | } | ||||||||
3015 | else { | ||||||||
3016 | mit->outer = NpyIter_MultiNew(nops, index_arrays, outer_flags, | ||||||||
3017 | NPY_KEEPORDER, NPY_UNSAFE_CASTING, op_flags, dtypes); | ||||||||
3018 | } | ||||||||
3019 | |||||||||
3020 | } | ||||||||
3021 | else { | ||||||||
3022 | /* TODO: Maybe add test for the CORDER, and maybe also allow F */ | ||||||||
3023 | mit->outer = NpyIter_MultiNew(nops, index_arrays, outer_flags, | ||||||||
3024 | NPY_CORDER, NPY_UNSAFE_CASTING, op_flags, dtypes); | ||||||||
3025 | } | ||||||||
3026 | |||||||||
3027 | /* NpyIter cleanup and information: */ | ||||||||
3028 | if (dummy_array) { | ||||||||
3029 | Py_DECREF(index_arrays[0])_Py_DECREF(((PyObject*)(index_arrays[0]))); | ||||||||
3030 | } | ||||||||
3031 | if (mit->outer == NULL((void*)0)) { | ||||||||
3032 | goto fail; | ||||||||
3033 | } | ||||||||
3034 | if (!uses_subspace) { | ||||||||
3035 | NpyIter_EnableExternalLoop(mit->outer); | ||||||||
3036 | } | ||||||||
3037 | |||||||||
3038 | mit->outer_next = NpyIter_GetIterNext(mit->outer, NULL((void*)0)); | ||||||||
3039 | if (mit->outer_next == NULL((void*)0)) { | ||||||||
3040 | goto fail; | ||||||||
3041 | } | ||||||||
3042 | mit->outer_ptrs = NpyIter_GetDataPtrArray(mit->outer); | ||||||||
3043 | if (!uses_subspace) { | ||||||||
3044 | mit->outer_strides = NpyIter_GetInnerStrideArray(mit->outer); | ||||||||
3045 | } | ||||||||
3046 | if (NpyIter_IterationNeedsAPI(mit->outer)) { | ||||||||
3047 | mit->needs_api = 1; | ||||||||
3048 | /* We may be doing a cast for the buffer, and that may have failed */ | ||||||||
3049 | if (PyErr_Occurred()) { | ||||||||
3050 | goto fail; | ||||||||
3051 | } | ||||||||
3052 | } | ||||||||
3053 | |||||||||
3054 | /* Get the allocated extra_op */ | ||||||||
3055 | if (extra_op_flags) { | ||||||||
3056 | if (extra_op == NULL((void*)0)) { | ||||||||
3057 | mit->extra_op = NpyIter_GetOperandArray(mit->outer)[mit->numiter]; | ||||||||
3058 | } | ||||||||
3059 | else { | ||||||||
3060 | mit->extra_op = extra_op; | ||||||||
3061 | } | ||||||||
3062 | Py_INCREF(mit->extra_op)_Py_INCREF(((PyObject*)(mit->extra_op))); | ||||||||
3063 | } | ||||||||
3064 | |||||||||
3065 | /* | ||||||||
3066 | * If extra_op is being tracked but subspace is used, we need | ||||||||
3067 | * to create a dedicated iterator for the outer iteration of | ||||||||
3068 | * the extra operand. | ||||||||
3069 | */ | ||||||||
3070 | if (extra_op_flags && uses_subspace) { | ||||||||
3071 | op_axes[0] = single_op_axis; | ||||||||
3072 | mit->extra_op_iter = NpyIter_AdvancedNew(1, &extra_op, | ||||||||
3073 | NPY_ITER_ZEROSIZE_OK0x00000040 | | ||||||||
3074 | NPY_ITER_REFS_OK0x00000020 | | ||||||||
3075 | NPY_ITER_GROWINNER0x00000400, | ||||||||
3076 | NPY_CORDER, | ||||||||
3077 | NPY_NO_CASTING, | ||||||||
3078 | &extra_op_flags, | ||||||||
3079 | NULL((void*)0), | ||||||||
3080 | mit->nd_fancy, op_axes, | ||||||||
3081 | mit->dimensions, 0); | ||||||||
3082 | |||||||||
3083 | if (mit->extra_op_iter == NULL((void*)0)) { | ||||||||
3084 | goto fail; | ||||||||
3085 | } | ||||||||
3086 | |||||||||
3087 | mit->extra_op_next = NpyIter_GetIterNext(mit->extra_op_iter, NULL((void*)0)); | ||||||||
3088 | if (mit->extra_op_next == NULL((void*)0)) { | ||||||||
3089 | goto fail; | ||||||||
3090 | } | ||||||||
3091 | mit->extra_op_ptrs = NpyIter_GetDataPtrArray(mit->extra_op_iter); | ||||||||
3092 | } | ||||||||
3093 | |||||||||
3094 | /* Get the full dimension information */ | ||||||||
3095 | if (subspace != NULL((void*)0)) { | ||||||||
3096 | mit->baseoffset = PyArray_BYTES(subspace); | ||||||||
3097 | } | ||||||||
3098 | else { | ||||||||
3099 | mit->baseoffset = PyArray_BYTES(arr); | ||||||||
3100 | } | ||||||||
3101 | |||||||||
3102 | /* Calculate total size of the MapIter */ | ||||||||
3103 | mit->size = PyArray_OverflowMultiplyList(mit->dimensions, mit->nd); | ||||||||
3104 | if (mit->size < 0) { | ||||||||
3105 | PyErr_SetString(PyExc_ValueError, | ||||||||
3106 | "advanced indexing operation result is too large"); | ||||||||
3107 | goto fail; | ||||||||
3108 | } | ||||||||
3109 | |||||||||
3110 | /* Can now return early if no subspace is being used */ | ||||||||
3111 | if (!uses_subspace) { | ||||||||
3112 | Py_XDECREF(extra_op)_Py_XDECREF(((PyObject*)(extra_op))); | ||||||||
3113 | Py_DECREF(intp_descr)_Py_DECREF(((PyObject*)(intp_descr))); | ||||||||
3114 | return (PyObject *)mit; | ||||||||
3115 | } | ||||||||
3116 | |||||||||
3117 | /* Fill in the last bit of mapiter information needed */ | ||||||||
3118 | |||||||||
3119 | /* | ||||||||
3120 | * Now just need to create the correct subspace iterator. | ||||||||
3121 | */ | ||||||||
3122 | index_arrays[0] = subspace; | ||||||||
3123 | dtypes[0] = NULL((void*)0); | ||||||||
3124 | op_flags[0] = subspace_flags; | ||||||||
3125 | op_axes[0] = NULL((void*)0); | ||||||||
3126 | |||||||||
3127 | if (extra_op_flags) { | ||||||||
3128 | /* We should iterate the extra_op as well */ | ||||||||
3129 | nops = 2; | ||||||||
3130 | index_arrays[1] = extra_op; | ||||||||
3131 | |||||||||
3132 | op_axes[1] = &single_op_axis[mit->nd_fancy]; | ||||||||
3133 | |||||||||
3134 | /* | ||||||||
3135 | * Buffering is never used here, but in case someone plugs it in | ||||||||
3136 | * somewhere else, set the type correctly then. | ||||||||
3137 | */ | ||||||||
3138 | if ((subspace_iter_flags & NPY_ITER_BUFFERED0x00000200)) { | ||||||||
3139 | dtypes[1] = extra_op_dtype; | ||||||||
3140 | } | ||||||||
3141 | else { | ||||||||
3142 | dtypes[1] = NULL((void*)0); | ||||||||
3143 | } | ||||||||
3144 | op_flags[1] = extra_op_flags; | ||||||||
3145 | } | ||||||||
3146 | else { | ||||||||
3147 | nops = 1; | ||||||||
3148 | } | ||||||||
3149 | |||||||||
3150 | mit->subspace_iter = NpyIter_AdvancedNew(nops, index_arrays, | ||||||||
3151 | NPY_ITER_ZEROSIZE_OK0x00000040 | | ||||||||
3152 | NPY_ITER_REFS_OK0x00000020 | | ||||||||
3153 | NPY_ITER_GROWINNER0x00000400 | | ||||||||
3154 | NPY_ITER_EXTERNAL_LOOP0x00000008 | | ||||||||
3155 | NPY_ITER_DELAY_BUFALLOC0x00000800 | | ||||||||
3156 | subspace_iter_flags, | ||||||||
3157 | (nops == 1 ? NPY_CORDER : NPY_KEEPORDER), | ||||||||
3158 | NPY_UNSAFE_CASTING, | ||||||||
3159 | op_flags, dtypes, | ||||||||
3160 | PyArray_NDIM(subspace), op_axes, | ||||||||
3161 | &mit->dimensions[mit->nd_fancy], 0); | ||||||||
3162 | |||||||||
3163 | if (mit->subspace_iter == NULL((void*)0)) { | ||||||||
3164 | goto fail; | ||||||||
3165 | } | ||||||||
3166 | |||||||||
3167 | mit->subspace_next = NpyIter_GetIterNext(mit->subspace_iter, NULL((void*)0)); | ||||||||
3168 | if (mit->subspace_next == NULL((void*)0)) { | ||||||||
3169 | goto fail; | ||||||||
3170 | } | ||||||||
3171 | mit->subspace_ptrs = NpyIter_GetDataPtrArray(mit->subspace_iter); | ||||||||
3172 | mit->subspace_strides = NpyIter_GetInnerStrideArray(mit->subspace_iter); | ||||||||
3173 | |||||||||
3174 | if (NpyIter_IterationNeedsAPI(mit->outer)) { | ||||||||
3175 | mit->needs_api = 1; | ||||||||
3176 | /* | ||||||||
3177 | * NOTE: In this case, need to call PyErr_Occurred() after | ||||||||
3178 | * basepointer resetting (buffer allocation) | ||||||||
3179 | */ | ||||||||
3180 | } | ||||||||
3181 | |||||||||
3182 | Py_XDECREF(extra_op)_Py_XDECREF(((PyObject*)(extra_op))); | ||||||||
3183 | Py_DECREF(intp_descr)_Py_DECREF(((PyObject*)(intp_descr))); | ||||||||
3184 | return (PyObject *)mit; | ||||||||
3185 | |||||||||
3186 | fail: | ||||||||
3187 | /* | ||||||||
3188 | * Check whether the operand could not be broadcast and replace the error | ||||||||
3189 | * in that case. This should however normally be found early with a | ||||||||
3190 | * direct goto to broadcast_error | ||||||||
3191 | */ | ||||||||
3192 | if (extra_op == NULL((void*)0)) { | ||||||||
3193 | goto finish; | ||||||||
3194 | } | ||||||||
3195 | |||||||||
3196 | j = mit->nd; | ||||||||
3197 | for (i = PyArray_NDIM(extra_op) - 1; i >= 0; i--) { | ||||||||
3198 | j--; | ||||||||
3199 | if ((PyArray_DIM(extra_op, i) != 1) && | ||||||||
3200 | /* (j < 0 is currently impossible, extra_op is reshaped) */ | ||||||||
3201 | j >= 0 && | ||||||||
3202 | PyArray_DIM(extra_op, i) != mit->dimensions[j]) { | ||||||||
3203 | /* extra_op cannot be broadcast to the indexing result */ | ||||||||
3204 | goto broadcast_error; | ||||||||
3205 | } | ||||||||
3206 | } | ||||||||
3207 | goto finish; | ||||||||
3208 | |||||||||
3209 | broadcast_error: | ||||||||
3210 | /* Report the shape of the original array if it exists */ | ||||||||
3211 | if (original_extra_op == NULL((void*)0)) { | ||||||||
3212 | original_extra_op = extra_op; | ||||||||
3213 | } | ||||||||
3214 | |||||||||
3215 | int extra_ndim = PyArray_NDIM(original_extra_op); | ||||||||
3216 | npy_intp *extra_dims = PyArray_DIMS(original_extra_op); | ||||||||
3217 | PyObject *shape1 = convert_shape_to_string(extra_ndim, extra_dims, ""); | ||||||||
3218 | if (shape1 == NULL((void*)0)) { | ||||||||
3219 | goto finish; | ||||||||
3220 | } | ||||||||
3221 | |||||||||
3222 | /* Unscramble the iterator shape for reporting when `mit->consec` is used */ | ||||||||
3223 | npy_intp transposed[NPY_MAXDIMS32]; | ||||||||
3224 | _get_transpose(mit->nd_fancy, mit->consec, mit->nd, 1, transposed); | ||||||||
3225 | for (i = 0; i < mit->nd; i++) { | ||||||||
3226 | transposed[i] = mit->dimensions[transposed[i]]; | ||||||||
3227 | } | ||||||||
3228 | |||||||||
3229 | PyObject *shape2 = convert_shape_to_string(mit->nd, transposed, ""); | ||||||||
3230 | if (shape2 == NULL((void*)0)) { | ||||||||
3231 | Py_DECREF(shape1)_Py_DECREF(((PyObject*)(shape1))); | ||||||||
3232 | goto finish; | ||||||||
3233 | } | ||||||||
3234 | |||||||||
3235 | PyErr_Format(PyExc_ValueError, | ||||||||
3236 | "shape mismatch: value array of shape %S could not be broadcast " | ||||||||
3237 | "to indexing result of shape %S", shape1, shape2); | ||||||||
3238 | |||||||||
3239 | Py_DECREF(shape1)_Py_DECREF(((PyObject*)(shape1))); | ||||||||
3240 | Py_DECREF(shape2)_Py_DECREF(((PyObject*)(shape2))); | ||||||||
3241 | |||||||||
3242 | finish: | ||||||||
3243 | Py_XDECREF(extra_op)_Py_XDECREF(((PyObject*)(extra_op))); | ||||||||
3244 | Py_DECREF(intp_descr)_Py_DECREF(((PyObject*)(intp_descr))); | ||||||||
3245 | Py_DECREF(mit)_Py_DECREF(((PyObject*)(mit))); | ||||||||
3246 | return NULL((void*)0); | ||||||||
3247 | } | ||||||||
3248 | |||||||||
3249 | |||||||||
3250 | /*NUMPY_API | ||||||||
3251 | * | ||||||||
3252 | * Same as PyArray_MapIterArray, but: | ||||||||
3253 | * | ||||||||
3254 | * If copy_if_overlap != 0, check if `a` has memory overlap with any of the | ||||||||
3255 | * arrays in `index` and with `extra_op`. If yes, make copies as appropriate | ||||||||
3256 | * to avoid problems if `a` is modified during the iteration. | ||||||||
3257 | * `iter->array` may contain a copied array (UPDATEIFCOPY/WRITEBACKIFCOPY set). | ||||||||
3258 | */ | ||||||||
3259 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||
3260 | PyArray_MapIterArrayCopyIfOverlap(PyArrayObject * a, PyObject * index, | ||||||||
3261 | int copy_if_overlap, PyArrayObject *extra_op) | ||||||||
3262 | { | ||||||||
3263 | PyArrayMapIterObject * mit = NULL((void*)0); | ||||||||
3264 | PyArrayObject *subspace = NULL((void*)0); | ||||||||
3265 | npy_index_info indices[NPY_MAXDIMS32 * 2 + 1]; | ||||||||
3266 | int i, index_num, ndim, fancy_ndim, index_type; | ||||||||
3267 | PyArrayObject *a_copy = NULL((void*)0); | ||||||||
3268 | |||||||||
3269 | index_type = prepare_index(a, index, indices, &index_num, | ||||||||
3270 | &ndim, &fancy_ndim, 0); | ||||||||
3271 | |||||||||
3272 | if (index_type < 0) { | ||||||||
3273 | return NULL((void*)0); | ||||||||
3274 | } | ||||||||
3275 | |||||||||
3276 | if (copy_if_overlap && index_has_memory_overlap(a, index_type, indices, | ||||||||
3277 | index_num, | ||||||||
3278 | (PyObject *)extra_op)) { | ||||||||
3279 | /* Make a copy of the input array */ | ||||||||
3280 | a_copy = (PyArrayObject *)PyArray_NewLikeArray(a, NPY_ANYORDER, | ||||||||
3281 | NULL((void*)0), 0); | ||||||||
3282 | if (a_copy == NULL((void*)0)) { | ||||||||
3283 | goto fail; | ||||||||
3284 | } | ||||||||
3285 | |||||||||
3286 | if (PyArray_CopyInto(a_copy, a) != 0) { | ||||||||
3287 | goto fail; | ||||||||
3288 | } | ||||||||
3289 | |||||||||
3290 | Py_INCREF(a)_Py_INCREF(((PyObject*)(a))); | ||||||||
3291 | if (PyArray_SetWritebackIfCopyBase(a_copy, a) < 0) { | ||||||||
3292 | goto fail; | ||||||||
3293 | } | ||||||||
3294 | |||||||||
3295 | a = a_copy; | ||||||||
3296 | } | ||||||||
3297 | |||||||||
3298 | /* If it is not a pure fancy index, need to get the subspace */ | ||||||||
3299 | if (index_type != HAS_FANCY) { | ||||||||
3300 | if (get_view_from_index(a, &subspace, indices, index_num, 1) < 0) { | ||||||||
3301 | goto fail; | ||||||||
3302 | } | ||||||||
3303 | } | ||||||||
3304 | |||||||||
3305 | mit = (PyArrayMapIterObject *)PyArray_MapIterNew(indices, index_num, | ||||||||
3306 | index_type, ndim, | ||||||||
3307 | fancy_ndim, | ||||||||
3308 | a, subspace, 0, | ||||||||
3309 | NPY_ITER_READWRITE0x00010000, | ||||||||
3310 | 0, NULL((void*)0), NULL((void*)0)); | ||||||||
3311 | if (mit == NULL((void*)0)) { | ||||||||
3312 | goto fail; | ||||||||
3313 | } | ||||||||
3314 | |||||||||
3315 | /* Required for backward compatibility */ | ||||||||
3316 | mit->ait = (PyArrayIterObject *)PyArray_IterNew((PyObject *)a); | ||||||||
3317 | if (mit->ait == NULL((void*)0)) { | ||||||||
3318 | goto fail; | ||||||||
3319 | } | ||||||||
3320 | |||||||||
3321 | if (PyArray_MapIterCheckIndices(mit) < 0) { | ||||||||
3322 | goto fail; | ||||||||
3323 | } | ||||||||
3324 | |||||||||
3325 | Py_XDECREF(a_copy)_Py_XDECREF(((PyObject*)(a_copy))); | ||||||||
3326 | Py_XDECREF(subspace)_Py_XDECREF(((PyObject*)(subspace))); | ||||||||
3327 | PyArray_MapIterReset(mit); | ||||||||
3328 | |||||||||
3329 | for (i=0; i < index_num; i++) { | ||||||||
3330 | Py_XDECREF(indices[i].object)_Py_XDECREF(((PyObject*)(indices[i].object))); | ||||||||
3331 | } | ||||||||
3332 | |||||||||
3333 | return (PyObject *)mit; | ||||||||
3334 | |||||||||
3335 | fail: | ||||||||
3336 | Py_XDECREF(a_copy)_Py_XDECREF(((PyObject*)(a_copy))); | ||||||||
3337 | Py_XDECREF(subspace)_Py_XDECREF(((PyObject*)(subspace))); | ||||||||
3338 | Py_XDECREF((PyObject *)mit)_Py_XDECREF(((PyObject*)((PyObject *)mit))); | ||||||||
3339 | for (i = 0; i < index_num; i++) { | ||||||||
3340 | Py_XDECREF(indices[i].object)_Py_XDECREF(((PyObject*)(indices[i].object))); | ||||||||
3341 | } | ||||||||
3342 | return NULL((void*)0); | ||||||||
3343 | } | ||||||||
3344 | |||||||||
3345 | |||||||||
3346 | /*NUMPY_API | ||||||||
3347 | * | ||||||||
3348 | * Use advanced indexing to iterate an array. | ||||||||
3349 | */ | ||||||||
3350 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||
3351 | PyArray_MapIterArray(PyArrayObject * a, PyObject * index) | ||||||||
3352 | { | ||||||||
3353 | return PyArray_MapIterArrayCopyIfOverlap(a, index, 0, NULL((void*)0)); | ||||||||
3354 | } | ||||||||
3355 | |||||||||
3356 | |||||||||
3357 | #undef HAS_INTEGER | ||||||||
3358 | #undef HAS_NEWAXIS | ||||||||
3359 | #undef HAS_SLICE | ||||||||
3360 | #undef HAS_ELLIPSIS | ||||||||
3361 | #undef HAS_FANCY | ||||||||
3362 | #undef HAS_BOOL | ||||||||
3363 | #undef HAS_SCALAR_ARRAY | ||||||||
3364 | #undef HAS_0D_BOOL | ||||||||
3365 | |||||||||
3366 | |||||||||
3367 | static void | ||||||||
3368 | arraymapiter_dealloc(PyArrayMapIterObject *mit) | ||||||||
3369 | { | ||||||||
3370 | PyArray_ResolveWritebackIfCopy(mit->array); | ||||||||
3371 | Py_XDECREF(mit->array)_Py_XDECREF(((PyObject*)(mit->array))); | ||||||||
3372 | Py_XDECREF(mit->ait)_Py_XDECREF(((PyObject*)(mit->ait))); | ||||||||
3373 | Py_XDECREF(mit->subspace)_Py_XDECREF(((PyObject*)(mit->subspace))); | ||||||||
3374 | Py_XDECREF(mit->extra_op)_Py_XDECREF(((PyObject*)(mit->extra_op))); | ||||||||
3375 | Py_XDECREF(mit->extra_op_dtype)_Py_XDECREF(((PyObject*)(mit->extra_op_dtype))); | ||||||||
3376 | if (mit->outer != NULL((void*)0)) { | ||||||||
3377 | NpyIter_Deallocate(mit->outer); | ||||||||
3378 | } | ||||||||
3379 | if (mit->subspace_iter != NULL((void*)0)) { | ||||||||
3380 | NpyIter_Deallocate(mit->subspace_iter); | ||||||||
3381 | } | ||||||||
3382 | if (mit->extra_op_iter != NULL((void*)0)) { | ||||||||
3383 | NpyIter_Deallocate(mit->extra_op_iter); | ||||||||
3384 | } | ||||||||
3385 | PyArray_freePyMem_RawFree(mit); | ||||||||
3386 | } | ||||||||
3387 | |||||||||
3388 | /* | ||||||||
3389 | * The mapiter object must be created new each time. It does not work | ||||||||
3390 | * to bind to a new array, and continue. | ||||||||
3391 | * | ||||||||
3392 | * This was the original intention, but currently that does not work. | ||||||||
3393 | * Do not expose the MapIter_Type to Python. | ||||||||
3394 | * | ||||||||
3395 | * The original mapiter(indexobj); mapiter.bind(a); idea is now fully | ||||||||
3396 | * removed. This is not very useful anyway, since mapiter is equivalent | ||||||||
3397 | * to a[indexobj].flat but the latter gets to use slice syntax. | ||||||||
3398 | */ | ||||||||
3399 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyTypeObject PyArrayMapIter_Type = { | ||||||||
3400 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | ||||||||
3401 | .tp_name = "numpy.mapiter", | ||||||||
3402 | .tp_basicsize = sizeof(PyArrayMapIterObject), | ||||||||
3403 | .tp_dealloc = (destructor)arraymapiter_dealloc, | ||||||||
3404 | .tp_flags = Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0), | ||||||||
3405 | }; |
1 | #define PY_SSIZE_T_CLEAN | ||||||||||||||||
2 | #include <Python.h> | ||||||||||||||||
3 | #include "structmember.h" | ||||||||||||||||
4 | |||||||||||||||||
5 | #define NPY_NO_DEPRECATED_API0x0000000E NPY_API_VERSION0x0000000E | ||||||||||||||||
6 | #define _MULTIARRAYMODULE | ||||||||||||||||
7 | #include "numpy/arrayobject.h" | ||||||||||||||||
8 | #include "numpy/arrayscalars.h" | ||||||||||||||||
9 | |||||||||||||||||
10 | #include "numpy/npy_math.h" | ||||||||||||||||
11 | |||||||||||||||||
12 | #include "npy_config.h" | ||||||||||||||||
13 | |||||||||||||||||
14 | #include "npy_ctypes.h" | ||||||||||||||||
15 | #include "npy_pycompat.h" | ||||||||||||||||
16 | #include "multiarraymodule.h" | ||||||||||||||||
17 | |||||||||||||||||
18 | #include "common.h" | ||||||||||||||||
19 | #include "ctors.h" | ||||||||||||||||
20 | #include "convert_datatype.h" | ||||||||||||||||
21 | #include "shape.h" | ||||||||||||||||
22 | #include "npy_buffer.h" | ||||||||||||||||
23 | #include "lowlevel_strided_loops.h" | ||||||||||||||||
24 | #include "_datetime.h" | ||||||||||||||||
25 | #include "datetime_strings.h" | ||||||||||||||||
26 | #include "array_assign.h" | ||||||||||||||||
27 | #include "mapping.h" /* for array_item_asarray */ | ||||||||||||||||
28 | #include "templ_common.h" /* for npy_mul_with_overflow_intp */ | ||||||||||||||||
29 | #include "alloc.h" | ||||||||||||||||
30 | #include <assert.h> | ||||||||||||||||
31 | |||||||||||||||||
32 | #include "get_attr_string.h" | ||||||||||||||||
33 | #include "array_coercion.h" | ||||||||||||||||
34 | |||||||||||||||||
35 | /* | ||||||||||||||||
36 | * Reading from a file or a string. | ||||||||||||||||
37 | * | ||||||||||||||||
38 | * As much as possible, we try to use the same code for both files and strings, | ||||||||||||||||
39 | * so the semantics for fromstring and fromfile are the same, especially with | ||||||||||||||||
40 | * regards to the handling of text representations. | ||||||||||||||||
41 | */ | ||||||||||||||||
42 | |||||||||||||||||
43 | /* | ||||||||||||||||
44 | * Scanning function for next element parsing and separator skipping. | ||||||||||||||||
45 | * These functions return: | ||||||||||||||||
46 | * - 0 to indicate more data to read | ||||||||||||||||
47 | * - -1 when reading stopped at the end of the string/file | ||||||||||||||||
48 | * - -2 when reading stopped before the end was reached. | ||||||||||||||||
49 | * | ||||||||||||||||
50 | * The dtype specific parsing functions may set the python error state | ||||||||||||||||
51 | * (they have to get the GIL first) additionally. | ||||||||||||||||
52 | */ | ||||||||||||||||
53 | typedef int (*next_element)(void **, void *, PyArray_Descr *, void *); | ||||||||||||||||
54 | typedef int (*skip_separator)(void **, const char *, void *); | ||||||||||||||||
55 | |||||||||||||||||
56 | |||||||||||||||||
57 | static npy_bool | ||||||||||||||||
58 | string_is_fully_read(char const* start, char const* end) { | ||||||||||||||||
59 | if (end == NULL((void*)0)) { | ||||||||||||||||
60 | return *start == '\0'; /* null terminated */ | ||||||||||||||||
61 | } | ||||||||||||||||
62 | else { | ||||||||||||||||
63 | return start >= end; /* fixed length */ | ||||||||||||||||
64 | } | ||||||||||||||||
65 | } | ||||||||||||||||
66 | |||||||||||||||||
67 | |||||||||||||||||
68 | static int | ||||||||||||||||
69 | fromstr_next_element(char **s, void *dptr, PyArray_Descr *dtype, | ||||||||||||||||
70 | const char *end) | ||||||||||||||||
71 | { | ||||||||||||||||
72 | char *e = *s; | ||||||||||||||||
73 | int r = dtype->f->fromstr(*s, dptr, &e, dtype); | ||||||||||||||||
74 | /* | ||||||||||||||||
75 | * fromstr always returns 0 for basic dtypes; s points to the end of the | ||||||||||||||||
76 | * parsed string. If s is not changed an error occurred or the end was | ||||||||||||||||
77 | * reached. | ||||||||||||||||
78 | */ | ||||||||||||||||
79 | if (*s == e || r < 0) { | ||||||||||||||||
80 | /* Nothing read, could be end of string or an error (or both) */ | ||||||||||||||||
81 | if (string_is_fully_read(*s, end)) { | ||||||||||||||||
82 | return -1; | ||||||||||||||||
83 | } | ||||||||||||||||
84 | return -2; | ||||||||||||||||
85 | } | ||||||||||||||||
86 | *s = e; | ||||||||||||||||
87 | if (end != NULL((void*)0) && *s > end) { | ||||||||||||||||
88 | /* Stop the iteration if we read far enough */ | ||||||||||||||||
89 | return -1; | ||||||||||||||||
90 | } | ||||||||||||||||
91 | return 0; | ||||||||||||||||
92 | } | ||||||||||||||||
93 | |||||||||||||||||
94 | static int | ||||||||||||||||
95 | fromfile_next_element(FILE **fp, void *dptr, PyArray_Descr *dtype, | ||||||||||||||||
96 | void *NPY_UNUSED(stream_data)(__NPY_UNUSED_TAGGEDstream_data) __attribute__ ((__unused__))) | ||||||||||||||||
97 | { | ||||||||||||||||
98 | /* the NULL argument is for backwards-compatibility */ | ||||||||||||||||
99 | int r = dtype->f->scanfunc(*fp, dptr, NULL((void*)0), dtype); | ||||||||||||||||
100 | /* r can be EOF or the number of items read (0 or 1) */ | ||||||||||||||||
101 | if (r == 1) { | ||||||||||||||||
102 | return 0; | ||||||||||||||||
103 | } | ||||||||||||||||
104 | else if (r == EOF(-1)) { | ||||||||||||||||
105 | return -1; | ||||||||||||||||
106 | } | ||||||||||||||||
107 | else { | ||||||||||||||||
108 | /* unable to read more, but EOF not reached indicating an error. */ | ||||||||||||||||
109 | return -2; | ||||||||||||||||
110 | } | ||||||||||||||||
111 | } | ||||||||||||||||
112 | |||||||||||||||||
113 | /* | ||||||||||||||||
114 | * Remove multiple whitespace from the separator, and add a space to the | ||||||||||||||||
115 | * beginning and end. This simplifies the separator-skipping code below. | ||||||||||||||||
116 | */ | ||||||||||||||||
117 | static char * | ||||||||||||||||
118 | swab_separator(const char *sep) | ||||||||||||||||
119 | { | ||||||||||||||||
120 | int skip_space = 0; | ||||||||||||||||
121 | char *s, *start; | ||||||||||||||||
122 | |||||||||||||||||
123 | s = start = malloc(strlen(sep)+3); | ||||||||||||||||
124 | if (s == NULL((void*)0)) { | ||||||||||||||||
125 | PyErr_NoMemory(); | ||||||||||||||||
126 | return NULL((void*)0); | ||||||||||||||||
127 | } | ||||||||||||||||
128 | /* add space to front if there isn't one */ | ||||||||||||||||
129 | if (*sep != '\0' && !isspace(*sep)((*__ctype_b_loc ())[(int) ((*sep))] & (unsigned short int ) _ISspace)) { | ||||||||||||||||
130 | *s = ' '; s++; | ||||||||||||||||
131 | } | ||||||||||||||||
132 | while (*sep != '\0') { | ||||||||||||||||
133 | if (isspace(*sep)((*__ctype_b_loc ())[(int) ((*sep))] & (unsigned short int ) _ISspace)) { | ||||||||||||||||
134 | if (skip_space) { | ||||||||||||||||
135 | sep++; | ||||||||||||||||
136 | } | ||||||||||||||||
137 | else { | ||||||||||||||||
138 | *s = ' '; | ||||||||||||||||
139 | s++; | ||||||||||||||||
140 | sep++; | ||||||||||||||||
141 | skip_space = 1; | ||||||||||||||||
142 | } | ||||||||||||||||
143 | } | ||||||||||||||||
144 | else { | ||||||||||||||||
145 | *s = *sep; | ||||||||||||||||
146 | s++; | ||||||||||||||||
147 | sep++; | ||||||||||||||||
148 | skip_space = 0; | ||||||||||||||||
149 | } | ||||||||||||||||
150 | } | ||||||||||||||||
151 | /* add space to end if there isn't one */ | ||||||||||||||||
152 | if (s != start && s[-1] == ' ') { | ||||||||||||||||
153 | *s = ' '; | ||||||||||||||||
154 | s++; | ||||||||||||||||
155 | } | ||||||||||||||||
156 | *s = '\0'; | ||||||||||||||||
157 | return start; | ||||||||||||||||
158 | } | ||||||||||||||||
159 | |||||||||||||||||
160 | /* | ||||||||||||||||
161 | * Assuming that the separator is the next bit in the string (file), skip it. | ||||||||||||||||
162 | * | ||||||||||||||||
163 | * Single spaces in the separator are matched to arbitrary-long sequences | ||||||||||||||||
164 | * of whitespace in the input. If the separator consists only of spaces, | ||||||||||||||||
165 | * it matches one or more whitespace characters. | ||||||||||||||||
166 | * | ||||||||||||||||
167 | * If we can't match the separator, return -2. | ||||||||||||||||
168 | * If we hit the end of the string (file), return -1. | ||||||||||||||||
169 | * Otherwise, return 0. | ||||||||||||||||
170 | */ | ||||||||||||||||
171 | static int | ||||||||||||||||
172 | fromstr_skip_separator(char **s, const char *sep, const char *end) | ||||||||||||||||
173 | { | ||||||||||||||||
174 | char *string = *s; | ||||||||||||||||
175 | int result = 0; | ||||||||||||||||
176 | |||||||||||||||||
177 | while (1) { | ||||||||||||||||
178 | char c = *string; | ||||||||||||||||
179 | if (string_is_fully_read(string, end)) { | ||||||||||||||||
180 | result = -1; | ||||||||||||||||
181 | break; | ||||||||||||||||
182 | } | ||||||||||||||||
183 | else if (*sep == '\0') { | ||||||||||||||||
184 | if (string != *s) { | ||||||||||||||||
185 | /* matched separator */ | ||||||||||||||||
186 | result = 0; | ||||||||||||||||
187 | break; | ||||||||||||||||
188 | } | ||||||||||||||||
189 | else { | ||||||||||||||||
190 | /* separator was whitespace wildcard that didn't match */ | ||||||||||||||||
191 | result = -2; | ||||||||||||||||
192 | break; | ||||||||||||||||
193 | } | ||||||||||||||||
194 | } | ||||||||||||||||
195 | else if (*sep == ' ') { | ||||||||||||||||
196 | /* whitespace wildcard */ | ||||||||||||||||
197 | if (!isspace(c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISspace )) { | ||||||||||||||||
198 | sep++; | ||||||||||||||||
199 | continue; | ||||||||||||||||
200 | } | ||||||||||||||||
201 | } | ||||||||||||||||
202 | else if (*sep != c) { | ||||||||||||||||
203 | result = -2; | ||||||||||||||||
204 | break; | ||||||||||||||||
205 | } | ||||||||||||||||
206 | else { | ||||||||||||||||
207 | sep++; | ||||||||||||||||
208 | } | ||||||||||||||||
209 | string++; | ||||||||||||||||
210 | } | ||||||||||||||||
211 | *s = string; | ||||||||||||||||
212 | return result; | ||||||||||||||||
213 | } | ||||||||||||||||
214 | |||||||||||||||||
215 | static int | ||||||||||||||||
216 | fromfile_skip_separator(FILE **fp, const char *sep, void *NPY_UNUSED(stream_data)(__NPY_UNUSED_TAGGEDstream_data) __attribute__ ((__unused__))) | ||||||||||||||||
217 | { | ||||||||||||||||
218 | int result = 0; | ||||||||||||||||
219 | const char *sep_start = sep; | ||||||||||||||||
220 | |||||||||||||||||
221 | while (1) { | ||||||||||||||||
222 | int c = fgetc(*fp); | ||||||||||||||||
223 | |||||||||||||||||
224 | if (c == EOF(-1)) { | ||||||||||||||||
225 | result = -1; | ||||||||||||||||
226 | break; | ||||||||||||||||
227 | } | ||||||||||||||||
228 | else if (*sep == '\0') { | ||||||||||||||||
229 | ungetc(c, *fp); | ||||||||||||||||
230 | if (sep != sep_start) { | ||||||||||||||||
231 | /* matched separator */ | ||||||||||||||||
232 | result = 0; | ||||||||||||||||
233 | break; | ||||||||||||||||
234 | } | ||||||||||||||||
235 | else { | ||||||||||||||||
236 | /* separator was whitespace wildcard that didn't match */ | ||||||||||||||||
237 | result = -2; | ||||||||||||||||
238 | break; | ||||||||||||||||
239 | } | ||||||||||||||||
240 | } | ||||||||||||||||
241 | else if (*sep == ' ') { | ||||||||||||||||
242 | /* whitespace wildcard */ | ||||||||||||||||
243 | if (!isspace(c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISspace )) { | ||||||||||||||||
244 | sep++; | ||||||||||||||||
245 | sep_start++; | ||||||||||||||||
246 | ungetc(c, *fp); | ||||||||||||||||
247 | } | ||||||||||||||||
248 | else if (sep == sep_start) { | ||||||||||||||||
249 | sep_start--; | ||||||||||||||||
250 | } | ||||||||||||||||
251 | } | ||||||||||||||||
252 | else if (*sep != c) { | ||||||||||||||||
253 | ungetc(c, *fp); | ||||||||||||||||
254 | result = -2; | ||||||||||||||||
255 | break; | ||||||||||||||||
256 | } | ||||||||||||||||
257 | else { | ||||||||||||||||
258 | sep++; | ||||||||||||||||
259 | } | ||||||||||||||||
260 | } | ||||||||||||||||
261 | return result; | ||||||||||||||||
262 | } | ||||||||||||||||
263 | |||||||||||||||||
264 | /* | ||||||||||||||||
265 | * Change a sub-array field to the base descriptor | ||||||||||||||||
266 | * and update the dimensions and strides | ||||||||||||||||
267 | * appropriately. Dimensions and strides are added | ||||||||||||||||
268 | * to the end. | ||||||||||||||||
269 | * | ||||||||||||||||
270 | * Strides are only added if given (because data is given). | ||||||||||||||||
271 | */ | ||||||||||||||||
272 | static int | ||||||||||||||||
273 | _update_descr_and_dimensions(PyArray_Descr **des, npy_intp *newdims, | ||||||||||||||||
274 | npy_intp *newstrides, int oldnd) | ||||||||||||||||
275 | { | ||||||||||||||||
276 | PyArray_Descr *old; | ||||||||||||||||
277 | int newnd; | ||||||||||||||||
278 | int numnew; | ||||||||||||||||
279 | npy_intp *mydim; | ||||||||||||||||
280 | int i; | ||||||||||||||||
281 | int tuple; | ||||||||||||||||
282 | |||||||||||||||||
283 | old = *des; | ||||||||||||||||
284 | *des = old->subarray->base; | ||||||||||||||||
285 | |||||||||||||||||
286 | |||||||||||||||||
287 | mydim = newdims + oldnd; | ||||||||||||||||
288 | tuple = PyTuple_Check(old->subarray->shape)((((((PyObject*)(old->subarray->shape))->ob_type))-> tp_flags & ((1UL << 26))) != 0); | ||||||||||||||||
289 | if (tuple) { | ||||||||||||||||
290 | numnew = PyTuple_GET_SIZE(old->subarray->shape)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(old->subarray ->shape))))->ob_size); | ||||||||||||||||
291 | } | ||||||||||||||||
292 | else { | ||||||||||||||||
293 | numnew = 1; | ||||||||||||||||
294 | } | ||||||||||||||||
295 | |||||||||||||||||
296 | |||||||||||||||||
297 | newnd = oldnd + numnew; | ||||||||||||||||
298 | if (newnd > NPY_MAXDIMS32) { | ||||||||||||||||
299 | goto finish; | ||||||||||||||||
300 | } | ||||||||||||||||
301 | if (tuple) { | ||||||||||||||||
302 | for (i = 0; i < numnew; i++) { | ||||||||||||||||
303 | mydim[i] = (npy_intp) PyLong_AsLong( | ||||||||||||||||
304 | PyTuple_GET_ITEM(old->subarray->shape, i)((((void) (0)), (PyTupleObject *)(old->subarray->shape) )->ob_item[i])); | ||||||||||||||||
305 | } | ||||||||||||||||
306 | } | ||||||||||||||||
307 | else { | ||||||||||||||||
308 | mydim[0] = (npy_intp) PyLong_AsLong(old->subarray->shape); | ||||||||||||||||
309 | } | ||||||||||||||||
310 | |||||||||||||||||
311 | if (newstrides) { | ||||||||||||||||
312 | npy_intp tempsize; | ||||||||||||||||
313 | npy_intp *mystrides; | ||||||||||||||||
314 | |||||||||||||||||
315 | mystrides = newstrides + oldnd; | ||||||||||||||||
316 | /* Make new strides -- always C-contiguous */ | ||||||||||||||||
317 | tempsize = (*des)->elsize; | ||||||||||||||||
318 | for (i = numnew - 1; i >= 0; i--) { | ||||||||||||||||
319 | mystrides[i] = tempsize; | ||||||||||||||||
320 | tempsize *= mydim[i] ? mydim[i] : 1; | ||||||||||||||||
321 | } | ||||||||||||||||
322 | } | ||||||||||||||||
323 | |||||||||||||||||
324 | finish: | ||||||||||||||||
325 | Py_INCREF(*des)_Py_INCREF(((PyObject*)(*des))); | ||||||||||||||||
326 | Py_DECREF(old)_Py_DECREF(((PyObject*)(old))); | ||||||||||||||||
327 | return newnd; | ||||||||||||||||
328 | } | ||||||||||||||||
329 | |||||||||||||||||
330 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) void | ||||||||||||||||
331 | _unaligned_strided_byte_copy(char *dst, npy_intp outstrides, char *src, | ||||||||||||||||
332 | npy_intp instrides, npy_intp N, int elsize) | ||||||||||||||||
333 | { | ||||||||||||||||
334 | npy_intp i; | ||||||||||||||||
335 | char *tout = dst; | ||||||||||||||||
336 | char *tin = src; | ||||||||||||||||
337 | |||||||||||||||||
338 | #define _COPY_N_SIZE(size) \ | ||||||||||||||||
339 | for(i=0; i<N; i++) { \ | ||||||||||||||||
340 | memcpy(tout, tin, size); \ | ||||||||||||||||
341 | tin += instrides; \ | ||||||||||||||||
342 | tout += outstrides; \ | ||||||||||||||||
343 | } \ | ||||||||||||||||
344 | return | ||||||||||||||||
345 | |||||||||||||||||
346 | switch(elsize) { | ||||||||||||||||
347 | case 8: | ||||||||||||||||
348 | _COPY_N_SIZE(8); | ||||||||||||||||
349 | case 4: | ||||||||||||||||
350 | _COPY_N_SIZE(4); | ||||||||||||||||
351 | case 1: | ||||||||||||||||
352 | _COPY_N_SIZE(1); | ||||||||||||||||
353 | case 2: | ||||||||||||||||
354 | _COPY_N_SIZE(2); | ||||||||||||||||
355 | case 16: | ||||||||||||||||
356 | _COPY_N_SIZE(16); | ||||||||||||||||
357 | default: | ||||||||||||||||
358 | _COPY_N_SIZE(elsize); | ||||||||||||||||
359 | } | ||||||||||||||||
360 | #undef _COPY_N_SIZE | ||||||||||||||||
361 | |||||||||||||||||
362 | } | ||||||||||||||||
363 | |||||||||||||||||
364 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) void | ||||||||||||||||
365 | _strided_byte_swap(void *p, npy_intp stride, npy_intp n, int size) | ||||||||||||||||
366 | { | ||||||||||||||||
367 | char *a, *b, c = 0; | ||||||||||||||||
368 | int j, m; | ||||||||||||||||
369 | |||||||||||||||||
370 | switch(size) { | ||||||||||||||||
371 | case 1: /* no byteswap necessary */ | ||||||||||||||||
372 | break; | ||||||||||||||||
373 | case 4: | ||||||||||||||||
374 | if (npy_is_aligned((void*)((npy_intp)p | stride), sizeof(npy_uint32))) { | ||||||||||||||||
375 | for (a = (char*)p; n > 0; n--, a += stride) { | ||||||||||||||||
376 | npy_uint32 * a_ = (npy_uint32 *)a; | ||||||||||||||||
377 | *a_ = npy_bswap4(*a_); | ||||||||||||||||
378 | } | ||||||||||||||||
379 | } | ||||||||||||||||
380 | else { | ||||||||||||||||
381 | for (a = (char*)p; n > 0; n--, a += stride) { | ||||||||||||||||
382 | npy_bswap4_unaligned(a); | ||||||||||||||||
383 | } | ||||||||||||||||
384 | } | ||||||||||||||||
385 | break; | ||||||||||||||||
386 | case 8: | ||||||||||||||||
387 | if (npy_is_aligned((void*)((npy_intp)p | stride), sizeof(npy_uint64))) { | ||||||||||||||||
388 | for (a = (char*)p; n > 0; n--, a += stride) { | ||||||||||||||||
389 | npy_uint64 * a_ = (npy_uint64 *)a; | ||||||||||||||||
390 | *a_ = npy_bswap8(*a_); | ||||||||||||||||
391 | } | ||||||||||||||||
392 | } | ||||||||||||||||
393 | else { | ||||||||||||||||
394 | for (a = (char*)p; n > 0; n--, a += stride) { | ||||||||||||||||
395 | npy_bswap8_unaligned(a); | ||||||||||||||||
396 | } | ||||||||||||||||
397 | } | ||||||||||||||||
398 | break; | ||||||||||||||||
399 | case 2: | ||||||||||||||||
400 | if (npy_is_aligned((void*)((npy_intp)p | stride), sizeof(npy_uint16))) { | ||||||||||||||||
401 | for (a = (char*)p; n > 0; n--, a += stride) { | ||||||||||||||||
402 | npy_uint16 * a_ = (npy_uint16 *)a; | ||||||||||||||||
403 | *a_ = npy_bswap2(*a_); | ||||||||||||||||
404 | } | ||||||||||||||||
405 | } | ||||||||||||||||
406 | else { | ||||||||||||||||
407 | for (a = (char*)p; n > 0; n--, a += stride) { | ||||||||||||||||
408 | npy_bswap2_unaligned(a); | ||||||||||||||||
409 | } | ||||||||||||||||
410 | } | ||||||||||||||||
411 | break; | ||||||||||||||||
412 | default: | ||||||||||||||||
413 | m = size/2; | ||||||||||||||||
414 | for (a = (char *)p; n > 0; n--, a += stride - m) { | ||||||||||||||||
415 | b = a + (size - 1); | ||||||||||||||||
416 | for (j = 0; j < m; j++) { | ||||||||||||||||
417 | c=*a; *a++ = *b; *b-- = c; | ||||||||||||||||
418 | } | ||||||||||||||||
419 | } | ||||||||||||||||
420 | break; | ||||||||||||||||
421 | } | ||||||||||||||||
422 | } | ||||||||||||||||
423 | |||||||||||||||||
424 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) void | ||||||||||||||||
425 | byte_swap_vector(void *p, npy_intp n, int size) | ||||||||||||||||
426 | { | ||||||||||||||||
427 | _strided_byte_swap(p, (npy_intp) size, n, size); | ||||||||||||||||
428 | return; | ||||||||||||||||
429 | } | ||||||||||||||||
430 | |||||||||||||||||
431 | /* If numitems > 1, then dst must be contiguous */ | ||||||||||||||||
432 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) void | ||||||||||||||||
433 | copy_and_swap(void *dst, void *src, int itemsize, npy_intp numitems, | ||||||||||||||||
434 | npy_intp srcstrides, int swap) | ||||||||||||||||
435 | { | ||||||||||||||||
436 | if ((numitems == 1) || (itemsize == srcstrides)) { | ||||||||||||||||
437 | memcpy(dst, src, itemsize*numitems); | ||||||||||||||||
438 | } | ||||||||||||||||
439 | else { | ||||||||||||||||
440 | npy_intp i; | ||||||||||||||||
441 | char *s1 = (char *)src; | ||||||||||||||||
442 | char *d1 = (char *)dst; | ||||||||||||||||
443 | |||||||||||||||||
444 | for (i = 0; i < numitems; i++) { | ||||||||||||||||
445 | memcpy(d1, s1, itemsize); | ||||||||||||||||
446 | d1 += itemsize; | ||||||||||||||||
447 | s1 += srcstrides; | ||||||||||||||||
448 | } | ||||||||||||||||
449 | } | ||||||||||||||||
450 | |||||||||||||||||
451 | if (swap) { | ||||||||||||||||
452 | byte_swap_vector(dst, numitems, itemsize); | ||||||||||||||||
453 | } | ||||||||||||||||
454 | } | ||||||||||||||||
455 | |||||||||||||||||
456 | |||||||||||||||||
457 | /* | ||||||||||||||||
458 | * Recursive helper to assign using a coercion cache. This function | ||||||||||||||||
459 | * must consume the cache depth first, just as the cache was originally | ||||||||||||||||
460 | * produced. | ||||||||||||||||
461 | */ | ||||||||||||||||
462 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||||||||||
463 | PyArray_AssignFromCache_Recursive( | ||||||||||||||||
464 | PyArrayObject *self, const int ndim, coercion_cache_obj **cache) | ||||||||||||||||
465 | { | ||||||||||||||||
466 | /* Consume first cache element by extracting information and freeing it */ | ||||||||||||||||
467 | PyObject *original_obj = (*cache)->converted_obj; | ||||||||||||||||
468 | PyObject *obj = (*cache)->arr_or_sequence; | ||||||||||||||||
469 | Py_INCREF(obj)_Py_INCREF(((PyObject*)(obj))); | ||||||||||||||||
470 | npy_bool sequence = (*cache)->sequence; | ||||||||||||||||
471 | int depth = (*cache)->depth; | ||||||||||||||||
472 | *cache = npy_unlink_coercion_cache(*cache); | ||||||||||||||||
473 | |||||||||||||||||
474 | /* | ||||||||||||||||
475 | * The maximum depth is special (specifically for objects), but usually | ||||||||||||||||
476 | * unrolled in the sequence branch below. | ||||||||||||||||
477 | */ | ||||||||||||||||
478 | if (NPY_UNLIKELY(depth == ndim)__builtin_expect(!!(depth == ndim), 0)) { | ||||||||||||||||
479 | /* | ||||||||||||||||
480 | * We have reached the maximum depth. We should simply assign to the | ||||||||||||||||
481 | * element in principle. There is one exception. If this is a 0-D | ||||||||||||||||
482 | * array being stored into a 0-D array (but we do not reach here then). | ||||||||||||||||
483 | */ | ||||||||||||||||
484 | if (PyArray_ISOBJECT(self)((PyArray_TYPE(self)) == NPY_OBJECT)) { | ||||||||||||||||
485 | assert(ndim != 0)((void) (0)); /* guaranteed by PyArray_AssignFromCache */ | ||||||||||||||||
486 | assert(PyArray_NDIM(self) == 0)((void) (0)); | ||||||||||||||||
487 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | ||||||||||||||||
488 | return PyArray_Pack(PyArray_DESCR(self), PyArray_BYTES(self), | ||||||||||||||||
489 | original_obj); | ||||||||||||||||
490 | } | ||||||||||||||||
491 | if (sequence) { | ||||||||||||||||
492 | /* | ||||||||||||||||
493 | * Sanity check which may be removed, the error is raised already | ||||||||||||||||
494 | * in `PyArray_DiscoverDTypeAndShape`. | ||||||||||||||||
495 | */ | ||||||||||||||||
496 | assert(0)((void) (0)); | ||||||||||||||||
497 | PyErr_SetString(PyExc_RuntimeError, | ||||||||||||||||
498 | "setting an array element with a sequence"); | ||||||||||||||||
499 | goto fail; | ||||||||||||||||
500 | } | ||||||||||||||||
501 | else if (original_obj != obj || !PyArray_CheckExact(obj)(((PyObject*)(obj))->ob_type == &PyArray_Type)) { | ||||||||||||||||
502 | /* | ||||||||||||||||
503 | * If the leave node is an array-like, but not a numpy array, | ||||||||||||||||
504 | * we pretend it is an arbitrary scalar. This means that in | ||||||||||||||||
505 | * most cases (where the dtype is int or float), we will end | ||||||||||||||||
506 | * up using float(array-like), or int(array-like). That does | ||||||||||||||||
507 | * not support general casting, but helps Quantity and masked | ||||||||||||||||
508 | * arrays, because it allows them to raise an error when | ||||||||||||||||
509 | * `__float__()` or `__int__()` is called. | ||||||||||||||||
510 | */ | ||||||||||||||||
511 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | ||||||||||||||||
512 | return PyArray_SETITEM(self, PyArray_BYTES(self), original_obj); | ||||||||||||||||
513 | } | ||||||||||||||||
514 | } | ||||||||||||||||
515 | |||||||||||||||||
516 | /* The element is either a sequence, or an array */ | ||||||||||||||||
517 | if (!sequence) { | ||||||||||||||||
518 | /* Straight forward array assignment */ | ||||||||||||||||
519 | assert(PyArray_Check(obj))((void) (0)); | ||||||||||||||||
520 | if (PyArray_CopyInto(self, (PyArrayObject *)obj) < 0) { | ||||||||||||||||
521 | goto fail; | ||||||||||||||||
522 | } | ||||||||||||||||
523 | } | ||||||||||||||||
524 | else { | ||||||||||||||||
525 | assert(depth != ndim)((void) (0)); | ||||||||||||||||
526 | npy_intp length = PySequence_LengthPySequence_Size(obj); | ||||||||||||||||
527 | if (length != PyArray_DIMS(self)[0]) { | ||||||||||||||||
528 | PyErr_SetString(PyExc_RuntimeError, | ||||||||||||||||
529 | "Inconsistent object during array creation? " | ||||||||||||||||
530 | "Content of sequences changed (length inconsistent)."); | ||||||||||||||||
531 | goto fail; | ||||||||||||||||
532 | } | ||||||||||||||||
533 | |||||||||||||||||
534 | for (npy_intp i = 0; i < length; i++) { | ||||||||||||||||
535 | PyObject *value = PySequence_Fast_GET_ITEM(obj, i)(((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? (((PyListObject *)(obj))->ob_item[ i]) : ((((void) (0)), (PyTupleObject *)(obj))->ob_item[i]) ); | ||||||||||||||||
536 | |||||||||||||||||
537 | if (*cache == NULL((void*)0) || (*cache)->converted_obj != value || | ||||||||||||||||
538 | (*cache)->depth != depth + 1) { | ||||||||||||||||
539 | if (ndim != depth + 1) { | ||||||||||||||||
540 | PyErr_SetString(PyExc_RuntimeError, | ||||||||||||||||
541 | "Inconsistent object during array creation? " | ||||||||||||||||
542 | "Content of sequences changed (now too shallow)."); | ||||||||||||||||
543 | goto fail; | ||||||||||||||||
544 | } | ||||||||||||||||
545 | /* Straight forward assignment of elements */ | ||||||||||||||||
546 | char *item; | ||||||||||||||||
547 | item = (PyArray_BYTES(self) + i * PyArray_STRIDES(self)[0]); | ||||||||||||||||
548 | if (PyArray_Pack(PyArray_DESCR(self), item, value) < 0) { | ||||||||||||||||
549 | goto fail; | ||||||||||||||||
550 | } | ||||||||||||||||
551 | } | ||||||||||||||||
552 | else { | ||||||||||||||||
553 | PyArrayObject *view; | ||||||||||||||||
554 | view = (PyArrayObject *)array_item_asarray(self, i); | ||||||||||||||||
555 | if (view == NULL((void*)0)) { | ||||||||||||||||
556 | goto fail; | ||||||||||||||||
557 | } | ||||||||||||||||
558 | if (PyArray_AssignFromCache_Recursive(view, ndim, cache) < 0) { | ||||||||||||||||
559 | Py_DECREF(view)_Py_DECREF(((PyObject*)(view))); | ||||||||||||||||
560 | goto fail; | ||||||||||||||||
561 | } | ||||||||||||||||
562 | Py_DECREF(view)_Py_DECREF(((PyObject*)(view))); | ||||||||||||||||
563 | } | ||||||||||||||||
564 | } | ||||||||||||||||
565 | } | ||||||||||||||||
566 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | ||||||||||||||||
567 | return 0; | ||||||||||||||||
568 | |||||||||||||||||
569 | fail: | ||||||||||||||||
570 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | ||||||||||||||||
571 | return -1; | ||||||||||||||||
572 | } | ||||||||||||||||
573 | |||||||||||||||||
574 | |||||||||||||||||
575 | /** | ||||||||||||||||
576 | * Fills an item based on a coercion cache object. It consumes the cache | ||||||||||||||||
577 | * object while doing so. | ||||||||||||||||
578 | * | ||||||||||||||||
579 | * @param self Array to fill. | ||||||||||||||||
580 | * @param cache coercion_cache_object, will be consumed. The cache must not | ||||||||||||||||
581 | * contain a single array (must start with a sequence). The array case | ||||||||||||||||
582 | * should be handled by `PyArray_FromArray()` before. | ||||||||||||||||
583 | * @return 0 on success -1 on failure. | ||||||||||||||||
584 | */ | ||||||||||||||||
585 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||||||||||
586 | PyArray_AssignFromCache(PyArrayObject *self, coercion_cache_obj *cache) { | ||||||||||||||||
587 | int ndim = PyArray_NDIM(self); | ||||||||||||||||
588 | /* | ||||||||||||||||
589 | * Do not support ndim == 0 now with an array in the cache. | ||||||||||||||||
590 | * The ndim == 0 is special because np.array(np.array(0), dtype=object) | ||||||||||||||||
591 | * should unpack the inner array. | ||||||||||||||||
592 | * Since the single-array case is special, it is handled previously | ||||||||||||||||
593 | * in either case. | ||||||||||||||||
594 | */ | ||||||||||||||||
595 | assert(cache->sequence)((void) (0)); | ||||||||||||||||
596 | assert(ndim != 0)((void) (0)); /* guaranteed if cache contains a sequence */ | ||||||||||||||||
597 | |||||||||||||||||
598 | if (PyArray_AssignFromCache_Recursive(self, ndim, &cache) < 0) { | ||||||||||||||||
599 | /* free the remaining cache. */ | ||||||||||||||||
600 | npy_free_coercion_cache(cache); | ||||||||||||||||
601 | return -1; | ||||||||||||||||
602 | } | ||||||||||||||||
603 | |||||||||||||||||
604 | /* | ||||||||||||||||
605 | * Sanity check, this is the initial call, and when it returns, the | ||||||||||||||||
606 | * cache has to be fully consumed, otherwise something is wrong. | ||||||||||||||||
607 | * NOTE: May be nicer to put into a recursion helper. | ||||||||||||||||
608 | */ | ||||||||||||||||
609 | if (cache != NULL((void*)0)) { | ||||||||||||||||
610 | PyErr_SetString(PyExc_RuntimeError, | ||||||||||||||||
611 | "Inconsistent object during array creation? " | ||||||||||||||||
612 | "Content of sequences changed (cache not consumed)."); | ||||||||||||||||
613 | npy_free_coercion_cache(cache); | ||||||||||||||||
614 | return -1; | ||||||||||||||||
615 | } | ||||||||||||||||
616 | return 0; | ||||||||||||||||
617 | } | ||||||||||||||||
618 | |||||||||||||||||
619 | |||||||||||||||||
620 | static void | ||||||||||||||||
621 | raise_memory_error(int nd, npy_intp const *dims, PyArray_Descr *descr) | ||||||||||||||||
622 | { | ||||||||||||||||
623 | static PyObject *exc_type = NULL((void*)0); | ||||||||||||||||
624 | |||||||||||||||||
625 | npy_cache_import( | ||||||||||||||||
626 | "numpy.core._exceptions", "_ArrayMemoryError", | ||||||||||||||||
627 | &exc_type); | ||||||||||||||||
628 | if (exc_type == NULL((void*)0)) { | ||||||||||||||||
629 | goto fail; | ||||||||||||||||
630 | } | ||||||||||||||||
631 | |||||||||||||||||
632 | PyObject *shape = PyArray_IntTupleFromIntp(nd, dims); | ||||||||||||||||
633 | if (shape == NULL((void*)0)) { | ||||||||||||||||
634 | goto fail; | ||||||||||||||||
635 | } | ||||||||||||||||
636 | |||||||||||||||||
637 | /* produce an error object */ | ||||||||||||||||
638 | PyObject *exc_value = PyTuple_Pack(2, shape, (PyObject *)descr); | ||||||||||||||||
639 | Py_DECREF(shape)_Py_DECREF(((PyObject*)(shape))); | ||||||||||||||||
640 | if (exc_value == NULL((void*)0)){ | ||||||||||||||||
641 | goto fail; | ||||||||||||||||
642 | } | ||||||||||||||||
643 | PyErr_SetObject(exc_type, exc_value); | ||||||||||||||||
644 | Py_DECREF(exc_value)_Py_DECREF(((PyObject*)(exc_value))); | ||||||||||||||||
645 | return; | ||||||||||||||||
646 | |||||||||||||||||
647 | fail: | ||||||||||||||||
648 | /* we couldn't raise the formatted exception for some reason */ | ||||||||||||||||
649 | PyErr_WriteUnraisable(NULL((void*)0)); | ||||||||||||||||
650 | PyErr_NoMemory(); | ||||||||||||||||
651 | } | ||||||||||||||||
652 | |||||||||||||||||
653 | /* | ||||||||||||||||
654 | * Generic new array creation routine. | ||||||||||||||||
655 | * Internal variant with calloc argument for PyArray_Zeros. | ||||||||||||||||
656 | * | ||||||||||||||||
657 | * steals a reference to descr. On failure or descr->subarray, descr will | ||||||||||||||||
658 | * be decrefed. | ||||||||||||||||
659 | */ | ||||||||||||||||
660 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
661 | PyArray_NewFromDescr_int( | ||||||||||||||||
662 | PyTypeObject *subtype, PyArray_Descr *descr, int nd, | ||||||||||||||||
663 | npy_intp const *dims, npy_intp const *strides, void *data, | ||||||||||||||||
664 | int flags, PyObject *obj, PyObject *base, int zeroed, | ||||||||||||||||
665 | int allow_emptystring) | ||||||||||||||||
666 | { | ||||||||||||||||
667 | PyArrayObject_fields *fa; | ||||||||||||||||
668 | npy_intp nbytes; | ||||||||||||||||
669 | |||||||||||||||||
670 | if (nd > NPY_MAXDIMS32 || nd < 0) { | ||||||||||||||||
671 | PyErr_Format(PyExc_ValueError, | ||||||||||||||||
672 | "number of dimensions must be within [0, %d]", NPY_MAXDIMS32); | ||||||||||||||||
673 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||||||||||||||
674 | return NULL((void*)0); | ||||||||||||||||
675 | } | ||||||||||||||||
676 | |||||||||||||||||
677 | if (descr->subarray) { | ||||||||||||||||
678 | PyObject *ret; | ||||||||||||||||
679 | npy_intp newdims[2*NPY_MAXDIMS32]; | ||||||||||||||||
680 | npy_intp *newstrides = NULL((void*)0); | ||||||||||||||||
681 | memcpy(newdims, dims, nd*sizeof(npy_intp)); | ||||||||||||||||
682 | if (strides) { | ||||||||||||||||
683 | newstrides = newdims + NPY_MAXDIMS32; | ||||||||||||||||
684 | memcpy(newstrides, strides, nd*sizeof(npy_intp)); | ||||||||||||||||
685 | } | ||||||||||||||||
686 | nd =_update_descr_and_dimensions(&descr, newdims, | ||||||||||||||||
687 | newstrides, nd); | ||||||||||||||||
688 | ret = PyArray_NewFromDescr_int( | ||||||||||||||||
689 | subtype, descr, | ||||||||||||||||
690 | nd, newdims, newstrides, data, | ||||||||||||||||
691 | flags, obj, base, | ||||||||||||||||
692 | zeroed, allow_emptystring); | ||||||||||||||||
693 | return ret; | ||||||||||||||||
694 | } | ||||||||||||||||
695 | |||||||||||||||||
696 | /* Check datatype element size */ | ||||||||||||||||
697 | nbytes = descr->elsize; | ||||||||||||||||
698 | if (PyDataType_ISUNSIZED(descr)((descr)->elsize == 0 && !(((PyArray_Descr *)(descr ))->names != ((void*)0)))) { | ||||||||||||||||
699 | if (!PyDataType_ISFLEXIBLE(descr)(((((PyArray_Descr*)(descr))->type_num) >=NPY_STRING) && ((((PyArray_Descr*)(descr))->type_num) <=NPY_VOID))) { | ||||||||||||||||
700 | PyErr_SetString(PyExc_TypeError, "Empty data-type"); | ||||||||||||||||
701 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||||||||||||||
702 | return NULL((void*)0); | ||||||||||||||||
703 | } | ||||||||||||||||
704 | else if (PyDataType_ISSTRING(descr)(((((PyArray_Descr*)(descr))->type_num) == NPY_STRING) || ( (((PyArray_Descr*)(descr))->type_num) == NPY_UNICODE)) && !allow_emptystring && | ||||||||||||||||
705 | data == NULL((void*)0)) { | ||||||||||||||||
706 | PyArray_DESCR_REPLACE(descr)do { PyArray_Descr *_new_; _new_ = PyArray_DescrNew(descr); _Py_XDECREF (((PyObject*)(descr))); descr = _new_; } while(0); | ||||||||||||||||
707 | if (descr == NULL((void*)0)) { | ||||||||||||||||
708 | return NULL((void*)0); | ||||||||||||||||
709 | } | ||||||||||||||||
710 | if (descr->type_num == NPY_STRING) { | ||||||||||||||||
711 | nbytes = descr->elsize = 1; | ||||||||||||||||
712 | } | ||||||||||||||||
713 | else { | ||||||||||||||||
714 | nbytes = descr->elsize = sizeof(npy_ucs4); | ||||||||||||||||
715 | } | ||||||||||||||||
716 | } | ||||||||||||||||
717 | } | ||||||||||||||||
718 | |||||||||||||||||
719 | fa = (PyArrayObject_fields *) subtype->tp_alloc(subtype, 0); | ||||||||||||||||
720 | if (fa == NULL((void*)0)) { | ||||||||||||||||
721 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||||||||||||||
722 | return NULL((void*)0); | ||||||||||||||||
723 | } | ||||||||||||||||
724 | fa->_buffer_info = NULL((void*)0); | ||||||||||||||||
725 | fa->nd = nd; | ||||||||||||||||
726 | fa->dimensions = NULL((void*)0); | ||||||||||||||||
727 | fa->data = NULL((void*)0); | ||||||||||||||||
728 | |||||||||||||||||
729 | if (data == NULL((void*)0)) { | ||||||||||||||||
730 | fa->flags = NPY_ARRAY_DEFAULT((0x0001 | (0x0100 | 0x0400))); | ||||||||||||||||
731 | if (flags) { | ||||||||||||||||
732 | fa->flags |= NPY_ARRAY_F_CONTIGUOUS0x0002; | ||||||||||||||||
733 | if (nd > 1) { | ||||||||||||||||
734 | fa->flags &= ~NPY_ARRAY_C_CONTIGUOUS0x0001; | ||||||||||||||||
735 | } | ||||||||||||||||
736 | flags = NPY_ARRAY_F_CONTIGUOUS0x0002; | ||||||||||||||||
737 | } | ||||||||||||||||
738 | } | ||||||||||||||||
739 | else { | ||||||||||||||||
740 | fa->flags = (flags & ~NPY_ARRAY_WRITEBACKIFCOPY0x2000); | ||||||||||||||||
741 | fa->flags &= ~NPY_ARRAY_UPDATEIFCOPY0x1000; | ||||||||||||||||
742 | } | ||||||||||||||||
743 | fa->descr = descr; | ||||||||||||||||
744 | fa->base = (PyObject *)NULL((void*)0); | ||||||||||||||||
745 | fa->weakreflist = (PyObject *)NULL((void*)0); | ||||||||||||||||
746 | |||||||||||||||||
747 | if (nd > 0) { | ||||||||||||||||
748 | fa->dimensions = npy_alloc_cache_dim(2 * nd); | ||||||||||||||||
749 | if (fa->dimensions == NULL((void*)0)) { | ||||||||||||||||
750 | PyErr_NoMemory(); | ||||||||||||||||
751 | goto fail; | ||||||||||||||||
752 | } | ||||||||||||||||
753 | fa->strides = fa->dimensions + nd; | ||||||||||||||||
754 | |||||||||||||||||
755 | /* Copy dimensions, check them, and find total array size `nbytes` */ | ||||||||||||||||
756 | for (int i = 0; i < nd; i++) { | ||||||||||||||||
757 | fa->dimensions[i] = dims[i]; | ||||||||||||||||
758 | |||||||||||||||||
759 | if (fa->dimensions[i] == 0) { | ||||||||||||||||
760 | /* | ||||||||||||||||
761 | * Compare to PyArray_OverflowMultiplyList that | ||||||||||||||||
762 | * returns 0 in this case. | ||||||||||||||||
763 | */ | ||||||||||||||||
764 | continue; | ||||||||||||||||
765 | } | ||||||||||||||||
766 | |||||||||||||||||
767 | if (fa->dimensions[i] < 0) { | ||||||||||||||||
768 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
769 | "negative dimensions are not allowed"); | ||||||||||||||||
770 | goto fail; | ||||||||||||||||
771 | } | ||||||||||||||||
772 | |||||||||||||||||
773 | /* | ||||||||||||||||
774 | * Care needs to be taken to avoid integer overflow when multiplying | ||||||||||||||||
775 | * the dimensions together to get the total size of the array. | ||||||||||||||||
776 | */ | ||||||||||||||||
777 | if (npy_mul_with_overflow_intp(&nbytes, nbytes, fa->dimensions[i])) { | ||||||||||||||||
778 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
779 | "array is too big; `arr.size * arr.dtype.itemsize` " | ||||||||||||||||
780 | "is larger than the maximum possible size."); | ||||||||||||||||
781 | goto fail; | ||||||||||||||||
782 | } | ||||||||||||||||
783 | } | ||||||||||||||||
784 | |||||||||||||||||
785 | /* Fill the strides (or copy them if they were passed in) */ | ||||||||||||||||
786 | if (strides == NULL((void*)0)) { | ||||||||||||||||
787 | /* fill the strides and set the contiguity flags */ | ||||||||||||||||
788 | _array_fill_strides(fa->strides, dims, nd, descr->elsize, | ||||||||||||||||
789 | flags, &(fa->flags)); | ||||||||||||||||
790 | } | ||||||||||||||||
791 | else { | ||||||||||||||||
792 | /* User to provided strides (user is responsible for correctness) */ | ||||||||||||||||
793 | for (int i = 0; i < nd; i++) { | ||||||||||||||||
794 | fa->strides[i] = strides[i]; | ||||||||||||||||
795 | } | ||||||||||||||||
796 | /* Since the strides were passed in must update contiguity */ | ||||||||||||||||
797 | PyArray_UpdateFlags((PyArrayObject *)fa, | ||||||||||||||||
798 | NPY_ARRAY_C_CONTIGUOUS0x0001|NPY_ARRAY_F_CONTIGUOUS0x0002); | ||||||||||||||||
799 | } | ||||||||||||||||
800 | } | ||||||||||||||||
801 | else { | ||||||||||||||||
802 | fa->dimensions = NULL((void*)0); | ||||||||||||||||
803 | fa->strides = NULL((void*)0); | ||||||||||||||||
804 | fa->flags |= NPY_ARRAY_C_CONTIGUOUS0x0001|NPY_ARRAY_F_CONTIGUOUS0x0002; | ||||||||||||||||
805 | } | ||||||||||||||||
806 | |||||||||||||||||
807 | if (data == NULL((void*)0)) { | ||||||||||||||||
808 | /* | ||||||||||||||||
809 | * Allocate something even for zero-space arrays | ||||||||||||||||
810 | * e.g. shape=(0,) -- otherwise buffer exposure | ||||||||||||||||
811 | * (a.data) doesn't work as it should. | ||||||||||||||||
812 | * Could probably just allocate a few bytes here. -- Chuck | ||||||||||||||||
813 | */ | ||||||||||||||||
814 | if (nbytes == 0) { | ||||||||||||||||
815 | nbytes = descr->elsize ? descr->elsize : 1; | ||||||||||||||||
816 | } | ||||||||||||||||
817 | /* | ||||||||||||||||
818 | * It is bad to have uninitialized OBJECT pointers | ||||||||||||||||
819 | * which could also be sub-fields of a VOID array | ||||||||||||||||
820 | */ | ||||||||||||||||
821 | if (zeroed || PyDataType_FLAGCHK(descr, NPY_NEEDS_INIT)(((descr)->flags & (0x08)) == (0x08))) { | ||||||||||||||||
822 | data = npy_alloc_cache_zero(nbytes); | ||||||||||||||||
823 | } | ||||||||||||||||
824 | else { | ||||||||||||||||
825 | data = npy_alloc_cache(nbytes); | ||||||||||||||||
826 | } | ||||||||||||||||
827 | if (data == NULL((void*)0)) { | ||||||||||||||||
828 | raise_memory_error(fa->nd, fa->dimensions, descr); | ||||||||||||||||
829 | goto fail; | ||||||||||||||||
830 | } | ||||||||||||||||
831 | fa->flags |= NPY_ARRAY_OWNDATA0x0004; | ||||||||||||||||
832 | } | ||||||||||||||||
833 | else { | ||||||||||||||||
834 | /* | ||||||||||||||||
835 | * If data is passed in, this object won't own it by default. | ||||||||||||||||
836 | * Caller must arrange for this to be reset if truly desired | ||||||||||||||||
837 | */ | ||||||||||||||||
838 | fa->flags &= ~NPY_ARRAY_OWNDATA0x0004; | ||||||||||||||||
839 | } | ||||||||||||||||
840 | fa->data = data; | ||||||||||||||||
841 | |||||||||||||||||
842 | /* | ||||||||||||||||
843 | * Always update the aligned flag. Not owned data or input strides may | ||||||||||||||||
844 | * not be aligned. Also on some platforms (debian sparc) malloc does not | ||||||||||||||||
845 | * provide enough alignment for long double types. | ||||||||||||||||
846 | */ | ||||||||||||||||
847 | PyArray_UpdateFlags((PyArrayObject *)fa, NPY_ARRAY_ALIGNED0x0100); | ||||||||||||||||
848 | |||||||||||||||||
849 | /* Set the base object. It's important to do it here so that | ||||||||||||||||
850 | * __array_finalize__ below receives it | ||||||||||||||||
851 | */ | ||||||||||||||||
852 | if (base != NULL((void*)0)) { | ||||||||||||||||
853 | Py_INCREF(base)_Py_INCREF(((PyObject*)(base))); | ||||||||||||||||
854 | if (PyArray_SetBaseObject((PyArrayObject *)fa, base) < 0) { | ||||||||||||||||
855 | goto fail; | ||||||||||||||||
856 | } | ||||||||||||||||
857 | } | ||||||||||||||||
858 | |||||||||||||||||
859 | /* | ||||||||||||||||
860 | * call the __array_finalize__ method if a subtype was requested. | ||||||||||||||||
861 | * If obj is NULL use Py_None for the Python callback. | ||||||||||||||||
862 | */ | ||||||||||||||||
863 | if (subtype != &PyArray_Type) { | ||||||||||||||||
864 | PyObject *res, *func; | ||||||||||||||||
865 | |||||||||||||||||
866 | func = PyObject_GetAttr((PyObject *)fa, npy_ma_str_array_finalize); | ||||||||||||||||
867 | if (func == NULL((void*)0)) { | ||||||||||||||||
868 | goto fail; | ||||||||||||||||
869 | } | ||||||||||||||||
870 | else if (func == Py_None(&_Py_NoneStruct)) { | ||||||||||||||||
871 | Py_DECREF(func)_Py_DECREF(((PyObject*)(func))); | ||||||||||||||||
872 | } | ||||||||||||||||
873 | else { | ||||||||||||||||
874 | if (PyCapsule_CheckExact(func)((((PyObject*)(func))->ob_type) == &PyCapsule_Type)) { | ||||||||||||||||
875 | /* A C-function is stored here */ | ||||||||||||||||
876 | PyArray_FinalizeFunc *cfunc; | ||||||||||||||||
877 | cfunc = PyCapsule_GetPointer(func, NULL((void*)0)); | ||||||||||||||||
878 | Py_DECREF(func)_Py_DECREF(((PyObject*)(func))); | ||||||||||||||||
879 | if (cfunc == NULL((void*)0)) { | ||||||||||||||||
880 | goto fail; | ||||||||||||||||
881 | } | ||||||||||||||||
882 | if (cfunc((PyArrayObject *)fa, obj) < 0) { | ||||||||||||||||
883 | goto fail; | ||||||||||||||||
884 | } | ||||||||||||||||
885 | } | ||||||||||||||||
886 | else { | ||||||||||||||||
887 | if (obj == NULL((void*)0)) { | ||||||||||||||||
888 | obj = Py_None(&_Py_NoneStruct); | ||||||||||||||||
889 | } | ||||||||||||||||
890 | res = PyObject_CallFunctionObjArgs(func, obj, NULL((void*)0)); | ||||||||||||||||
891 | Py_DECREF(func)_Py_DECREF(((PyObject*)(func))); | ||||||||||||||||
892 | if (res == NULL((void*)0)) { | ||||||||||||||||
893 | goto fail; | ||||||||||||||||
894 | } | ||||||||||||||||
895 | else { | ||||||||||||||||
896 | Py_DECREF(res)_Py_DECREF(((PyObject*)(res))); | ||||||||||||||||
897 | } | ||||||||||||||||
898 | } | ||||||||||||||||
899 | } | ||||||||||||||||
900 | } | ||||||||||||||||
901 | return (PyObject *)fa; | ||||||||||||||||
902 | |||||||||||||||||
903 | fail: | ||||||||||||||||
904 | Py_DECREF(fa)_Py_DECREF(((PyObject*)(fa))); | ||||||||||||||||
905 | return NULL((void*)0); | ||||||||||||||||
906 | } | ||||||||||||||||
907 | |||||||||||||||||
908 | |||||||||||||||||
909 | /*NUMPY_API | ||||||||||||||||
910 | * Generic new array creation routine. | ||||||||||||||||
911 | * | ||||||||||||||||
912 | * steals a reference to descr. On failure or when dtype->subarray is | ||||||||||||||||
913 | * true, dtype will be decrefed. | ||||||||||||||||
914 | */ | ||||||||||||||||
915 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
916 | PyArray_NewFromDescr( | ||||||||||||||||
917 | PyTypeObject *subtype, PyArray_Descr *descr, | ||||||||||||||||
918 | int nd, npy_intp const *dims, npy_intp const *strides, void *data, | ||||||||||||||||
919 | int flags, PyObject *obj) | ||||||||||||||||
920 | { | ||||||||||||||||
921 | return PyArray_NewFromDescrAndBase( | ||||||||||||||||
922 | subtype, descr, | ||||||||||||||||
923 | nd, dims, strides, data, | ||||||||||||||||
924 | flags, obj, NULL((void*)0)); | ||||||||||||||||
925 | } | ||||||||||||||||
926 | |||||||||||||||||
927 | /* | ||||||||||||||||
928 | * Sets the base object using PyArray_SetBaseObject | ||||||||||||||||
929 | */ | ||||||||||||||||
930 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
931 | PyArray_NewFromDescrAndBase( | ||||||||||||||||
932 | PyTypeObject *subtype, PyArray_Descr *descr, | ||||||||||||||||
933 | int nd, npy_intp const *dims, npy_intp const *strides, void *data, | ||||||||||||||||
934 | int flags, PyObject *obj, PyObject *base) | ||||||||||||||||
935 | { | ||||||||||||||||
936 | return PyArray_NewFromDescr_int(subtype, descr, nd, | ||||||||||||||||
937 | dims, strides, data, | ||||||||||||||||
938 | flags, obj, base, 0, 0); | ||||||||||||||||
939 | } | ||||||||||||||||
940 | |||||||||||||||||
941 | /* | ||||||||||||||||
942 | * Creates a new array with the same shape as the provided one, | ||||||||||||||||
943 | * with possible memory layout order, data type and shape changes. | ||||||||||||||||
944 | * | ||||||||||||||||
945 | * prototype - The array the new one should be like. | ||||||||||||||||
946 | * order - NPY_CORDER - C-contiguous result. | ||||||||||||||||
947 | * NPY_FORTRANORDER - Fortran-contiguous result. | ||||||||||||||||
948 | * NPY_ANYORDER - Fortran if prototype is Fortran, C otherwise. | ||||||||||||||||
949 | * NPY_KEEPORDER - Keeps the axis ordering of prototype. | ||||||||||||||||
950 | * dtype - If not NULL, overrides the data type of the result. | ||||||||||||||||
951 | * ndim - If not -1, overrides the shape of the result. | ||||||||||||||||
952 | * dims - If ndim is not -1, overrides the shape of the result. | ||||||||||||||||
953 | * subok - If 1, use the prototype's array subtype, otherwise | ||||||||||||||||
954 | * always create a base-class array. | ||||||||||||||||
955 | * | ||||||||||||||||
956 | * NOTE: If dtype is not NULL, steals the dtype reference. On failure or when | ||||||||||||||||
957 | * dtype->subarray is true, dtype will be decrefed. | ||||||||||||||||
958 | */ | ||||||||||||||||
959 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
960 | PyArray_NewLikeArrayWithShape(PyArrayObject *prototype, NPY_ORDER order, | ||||||||||||||||
961 | PyArray_Descr *dtype, int ndim, npy_intp const *dims, int subok) | ||||||||||||||||
962 | { | ||||||||||||||||
963 | PyObject *ret = NULL((void*)0); | ||||||||||||||||
964 | |||||||||||||||||
965 | if (ndim == -1) { | ||||||||||||||||
966 | ndim = PyArray_NDIM(prototype); | ||||||||||||||||
967 | dims = PyArray_DIMS(prototype); | ||||||||||||||||
968 | } | ||||||||||||||||
969 | else if (order == NPY_KEEPORDER && (ndim != PyArray_NDIM(prototype))) { | ||||||||||||||||
970 | order = NPY_CORDER; | ||||||||||||||||
971 | } | ||||||||||||||||
972 | |||||||||||||||||
973 | /* If no override data type, use the one from the prototype */ | ||||||||||||||||
974 | if (dtype == NULL((void*)0)) { | ||||||||||||||||
975 | dtype = PyArray_DESCR(prototype); | ||||||||||||||||
976 | Py_INCREF(dtype)_Py_INCREF(((PyObject*)(dtype))); | ||||||||||||||||
977 | } | ||||||||||||||||
978 | |||||||||||||||||
979 | /* Handle ANYORDER and simple KEEPORDER cases */ | ||||||||||||||||
980 | switch (order) { | ||||||||||||||||
981 | case NPY_ANYORDER: | ||||||||||||||||
982 | order = PyArray_ISFORTRAN(prototype)(PyArray_CHKFLAGS(prototype, 0x0002) && (!PyArray_CHKFLAGS (prototype, 0x0001))) ? | ||||||||||||||||
983 | NPY_FORTRANORDER : NPY_CORDER; | ||||||||||||||||
984 | break; | ||||||||||||||||
985 | case NPY_KEEPORDER: | ||||||||||||||||
986 | if (PyArray_IS_C_CONTIGUOUS(prototype)PyArray_CHKFLAGS((prototype), 0x0001) || ndim <= 1) { | ||||||||||||||||
987 | order = NPY_CORDER; | ||||||||||||||||
988 | break; | ||||||||||||||||
989 | } | ||||||||||||||||
990 | else if (PyArray_IS_F_CONTIGUOUS(prototype)PyArray_CHKFLAGS((prototype), 0x0002)) { | ||||||||||||||||
991 | order = NPY_FORTRANORDER; | ||||||||||||||||
992 | break; | ||||||||||||||||
993 | } | ||||||||||||||||
994 | break; | ||||||||||||||||
995 | default: | ||||||||||||||||
996 | break; | ||||||||||||||||
997 | } | ||||||||||||||||
998 | |||||||||||||||||
999 | /* If it's not KEEPORDER, this is simple */ | ||||||||||||||||
1000 | if (order != NPY_KEEPORDER) { | ||||||||||||||||
1001 | ret = PyArray_NewFromDescr(subok ? Py_TYPE(prototype)(((PyObject*)(prototype))->ob_type) : &PyArray_Type, | ||||||||||||||||
1002 | dtype, | ||||||||||||||||
1003 | ndim, | ||||||||||||||||
1004 | dims, | ||||||||||||||||
1005 | NULL((void*)0), | ||||||||||||||||
1006 | NULL((void*)0), | ||||||||||||||||
1007 | order, | ||||||||||||||||
1008 | subok ? (PyObject *)prototype : NULL((void*)0)); | ||||||||||||||||
1009 | } | ||||||||||||||||
1010 | /* KEEPORDER needs some analysis of the strides */ | ||||||||||||||||
1011 | else { | ||||||||||||||||
1012 | npy_intp strides[NPY_MAXDIMS32], stride; | ||||||||||||||||
1013 | npy_stride_sort_item strideperm[NPY_MAXDIMS32]; | ||||||||||||||||
1014 | int idim; | ||||||||||||||||
1015 | |||||||||||||||||
1016 | PyArray_CreateSortedStridePerm(ndim, | ||||||||||||||||
1017 | PyArray_STRIDES(prototype), | ||||||||||||||||
1018 | strideperm); | ||||||||||||||||
1019 | |||||||||||||||||
1020 | /* Build the new strides */ | ||||||||||||||||
1021 | stride = dtype->elsize; | ||||||||||||||||
1022 | for (idim = ndim-1; idim >= 0; --idim) { | ||||||||||||||||
1023 | npy_intp i_perm = strideperm[idim].perm; | ||||||||||||||||
1024 | strides[i_perm] = stride; | ||||||||||||||||
1025 | stride *= dims[i_perm]; | ||||||||||||||||
1026 | } | ||||||||||||||||
1027 | |||||||||||||||||
1028 | /* Finally, allocate the array */ | ||||||||||||||||
1029 | ret = PyArray_NewFromDescr(subok ? Py_TYPE(prototype)(((PyObject*)(prototype))->ob_type) : &PyArray_Type, | ||||||||||||||||
1030 | dtype, | ||||||||||||||||
1031 | ndim, | ||||||||||||||||
1032 | dims, | ||||||||||||||||
1033 | strides, | ||||||||||||||||
1034 | NULL((void*)0), | ||||||||||||||||
1035 | 0, | ||||||||||||||||
1036 | subok ? (PyObject *)prototype : NULL((void*)0)); | ||||||||||||||||
1037 | } | ||||||||||||||||
1038 | |||||||||||||||||
1039 | return ret; | ||||||||||||||||
1040 | } | ||||||||||||||||
1041 | |||||||||||||||||
1042 | /*NUMPY_API | ||||||||||||||||
1043 | * Creates a new array with the same shape as the provided one, | ||||||||||||||||
1044 | * with possible memory layout order and data type changes. | ||||||||||||||||
1045 | * | ||||||||||||||||
1046 | * prototype - The array the new one should be like. | ||||||||||||||||
1047 | * order - NPY_CORDER - C-contiguous result. | ||||||||||||||||
1048 | * NPY_FORTRANORDER - Fortran-contiguous result. | ||||||||||||||||
1049 | * NPY_ANYORDER - Fortran if prototype is Fortran, C otherwise. | ||||||||||||||||
1050 | * NPY_KEEPORDER - Keeps the axis ordering of prototype. | ||||||||||||||||
1051 | * dtype - If not NULL, overrides the data type of the result. | ||||||||||||||||
1052 | * subok - If 1, use the prototype's array subtype, otherwise | ||||||||||||||||
1053 | * always create a base-class array. | ||||||||||||||||
1054 | * | ||||||||||||||||
1055 | * NOTE: If dtype is not NULL, steals the dtype reference. On failure or when | ||||||||||||||||
1056 | * dtype->subarray is true, dtype will be decrefed. | ||||||||||||||||
1057 | */ | ||||||||||||||||
1058 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
1059 | PyArray_NewLikeArray(PyArrayObject *prototype, NPY_ORDER order, | ||||||||||||||||
1060 | PyArray_Descr *dtype, int subok) | ||||||||||||||||
1061 | { | ||||||||||||||||
1062 | return PyArray_NewLikeArrayWithShape(prototype, order, dtype, -1, NULL((void*)0), subok); | ||||||||||||||||
1063 | } | ||||||||||||||||
1064 | |||||||||||||||||
1065 | /*NUMPY_API | ||||||||||||||||
1066 | * Generic new array creation routine. | ||||||||||||||||
1067 | */ | ||||||||||||||||
1068 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
1069 | PyArray_New( | ||||||||||||||||
1070 | PyTypeObject *subtype, int nd, npy_intp const *dims, int type_num, | ||||||||||||||||
1071 | npy_intp const *strides, void *data, int itemsize, int flags, | ||||||||||||||||
1072 | PyObject *obj) | ||||||||||||||||
1073 | { | ||||||||||||||||
1074 | PyArray_Descr *descr; | ||||||||||||||||
1075 | PyObject *new; | ||||||||||||||||
1076 | |||||||||||||||||
1077 | descr = PyArray_DescrFromType(type_num); | ||||||||||||||||
1078 | if (descr == NULL((void*)0)) { | ||||||||||||||||
1079 | return NULL((void*)0); | ||||||||||||||||
1080 | } | ||||||||||||||||
1081 | if (PyDataType_ISUNSIZED(descr)((descr)->elsize == 0 && !(((PyArray_Descr *)(descr ))->names != ((void*)0)))) { | ||||||||||||||||
1082 | if (itemsize < 1) { | ||||||||||||||||
1083 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
1084 | "data type must provide an itemsize"); | ||||||||||||||||
1085 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||||||||||||||
1086 | return NULL((void*)0); | ||||||||||||||||
1087 | } | ||||||||||||||||
1088 | PyArray_DESCR_REPLACE(descr)do { PyArray_Descr *_new_; _new_ = PyArray_DescrNew(descr); _Py_XDECREF (((PyObject*)(descr))); descr = _new_; } while(0); | ||||||||||||||||
1089 | descr->elsize = itemsize; | ||||||||||||||||
1090 | } | ||||||||||||||||
1091 | new = PyArray_NewFromDescr(subtype, descr, nd, dims, strides, | ||||||||||||||||
1092 | data, flags, obj); | ||||||||||||||||
1093 | return new; | ||||||||||||||||
1094 | } | ||||||||||||||||
1095 | |||||||||||||||||
1096 | |||||||||||||||||
1097 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArray_Descr * | ||||||||||||||||
1098 | _dtype_from_buffer_3118(PyObject *memoryview) | ||||||||||||||||
1099 | { | ||||||||||||||||
1100 | PyArray_Descr *descr; | ||||||||||||||||
1101 | Py_buffer *view = PyMemoryView_GET_BUFFER(memoryview)(&((PyMemoryViewObject *)(memoryview))->view); | ||||||||||||||||
1102 | if (view->format != NULL((void*)0)) { | ||||||||||||||||
1103 | descr = _descriptor_from_pep3118_format(view->format); | ||||||||||||||||
1104 | if (descr == NULL((void*)0)) { | ||||||||||||||||
1105 | return NULL((void*)0); | ||||||||||||||||
1106 | } | ||||||||||||||||
1107 | } | ||||||||||||||||
1108 | else { | ||||||||||||||||
1109 | /* If no format is specified, just assume a byte array | ||||||||||||||||
1110 | * TODO: void would make more sense here, as it wouldn't null | ||||||||||||||||
1111 | * terminate. | ||||||||||||||||
1112 | */ | ||||||||||||||||
1113 | descr = PyArray_DescrNewFromType(NPY_STRING); | ||||||||||||||||
1114 | descr->elsize = view->itemsize; | ||||||||||||||||
1115 | } | ||||||||||||||||
1116 | return descr; | ||||||||||||||||
1117 | } | ||||||||||||||||
1118 | |||||||||||||||||
1119 | |||||||||||||||||
1120 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
1121 | _array_from_buffer_3118(PyObject *memoryview) | ||||||||||||||||
1122 | { | ||||||||||||||||
1123 | /* PEP 3118 */ | ||||||||||||||||
1124 | Py_buffer *view; | ||||||||||||||||
1125 | PyArray_Descr *descr = NULL((void*)0); | ||||||||||||||||
1126 | PyObject *r = NULL((void*)0); | ||||||||||||||||
1127 | int nd, flags; | ||||||||||||||||
1128 | Py_ssize_t d; | ||||||||||||||||
1129 | npy_intp shape[NPY_MAXDIMS32], strides[NPY_MAXDIMS32]; | ||||||||||||||||
1130 | |||||||||||||||||
1131 | view = PyMemoryView_GET_BUFFER(memoryview)(&((PyMemoryViewObject *)(memoryview))->view); | ||||||||||||||||
1132 | nd = view->ndim; | ||||||||||||||||
1133 | descr = _dtype_from_buffer_3118(memoryview); | ||||||||||||||||
1134 | |||||||||||||||||
1135 | if (descr == NULL((void*)0)) { | ||||||||||||||||
1136 | return NULL((void*)0); | ||||||||||||||||
1137 | } | ||||||||||||||||
1138 | |||||||||||||||||
1139 | /* Sanity check */ | ||||||||||||||||
1140 | if (descr->elsize != view->itemsize) { | ||||||||||||||||
1141 | /* Ctypes has bugs in its PEP3118 implementation, which we need to | ||||||||||||||||
1142 | * work around. | ||||||||||||||||
1143 | * | ||||||||||||||||
1144 | * bpo-10746 | ||||||||||||||||
1145 | * bpo-32780 | ||||||||||||||||
1146 | * bpo-32782 | ||||||||||||||||
1147 | * | ||||||||||||||||
1148 | * Note that even if the above are fixed in main, we have to drop the | ||||||||||||||||
1149 | * early patch versions of python to actually make use of the fixes. | ||||||||||||||||
1150 | */ | ||||||||||||||||
1151 | if (!npy_ctypes_check(Py_TYPE(view->obj)(((PyObject*)(view->obj))->ob_type))) { | ||||||||||||||||
1152 | /* This object has no excuse for a broken PEP3118 buffer */ | ||||||||||||||||
1153 | PyErr_Format( | ||||||||||||||||
1154 | PyExc_RuntimeError, | ||||||||||||||||
1155 | "Item size %zd for PEP 3118 buffer format " | ||||||||||||||||
1156 | "string %s does not match the dtype %c item size %d.", | ||||||||||||||||
1157 | view->itemsize, view->format, descr->type, | ||||||||||||||||
1158 | descr->elsize); | ||||||||||||||||
1159 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||||||||||||||
1160 | return NULL((void*)0); | ||||||||||||||||
1161 | } | ||||||||||||||||
1162 | |||||||||||||||||
1163 | if (PyErr_Warn(PyErr_WarnEx(PyExc_RuntimeWarning, "A builtin ctypes object gave a PEP3118 format " "string that does not match its itemsize, so a " "best-guess will be made of the data type. " "Newer versions of python may behave correctly.", 1) | ||||||||||||||||
1164 | PyExc_RuntimeWarning,PyErr_WarnEx(PyExc_RuntimeWarning, "A builtin ctypes object gave a PEP3118 format " "string that does not match its itemsize, so a " "best-guess will be made of the data type. " "Newer versions of python may behave correctly.", 1) | ||||||||||||||||
1165 | "A builtin ctypes object gave a PEP3118 format "PyErr_WarnEx(PyExc_RuntimeWarning, "A builtin ctypes object gave a PEP3118 format " "string that does not match its itemsize, so a " "best-guess will be made of the data type. " "Newer versions of python may behave correctly.", 1) | ||||||||||||||||
1166 | "string that does not match its itemsize, so a "PyErr_WarnEx(PyExc_RuntimeWarning, "A builtin ctypes object gave a PEP3118 format " "string that does not match its itemsize, so a " "best-guess will be made of the data type. " "Newer versions of python may behave correctly.", 1) | ||||||||||||||||
1167 | "best-guess will be made of the data type. "PyErr_WarnEx(PyExc_RuntimeWarning, "A builtin ctypes object gave a PEP3118 format " "string that does not match its itemsize, so a " "best-guess will be made of the data type. " "Newer versions of python may behave correctly.", 1) | ||||||||||||||||
1168 | "Newer versions of python may behave correctly.")PyErr_WarnEx(PyExc_RuntimeWarning, "A builtin ctypes object gave a PEP3118 format " "string that does not match its itemsize, so a " "best-guess will be made of the data type. " "Newer versions of python may behave correctly.", 1) < 0) { | ||||||||||||||||
1169 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||||||||||||||
1170 | return NULL((void*)0); | ||||||||||||||||
1171 | } | ||||||||||||||||
1172 | |||||||||||||||||
1173 | /* Thankfully, np.dtype(ctypes_type) works in most cases. | ||||||||||||||||
1174 | * For an array input, this produces a dtype containing all the | ||||||||||||||||
1175 | * dimensions, so the array is now 0d. | ||||||||||||||||
1176 | */ | ||||||||||||||||
1177 | nd = 0; | ||||||||||||||||
1178 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||||||||||||||
1179 | descr = (PyArray_Descr *)PyObject_CallFunctionObjArgs( | ||||||||||||||||
1180 | (PyObject *)&PyArrayDescr_Type(*(PyTypeObject *)(&PyArrayDescr_TypeFull)), Py_TYPE(view->obj)(((PyObject*)(view->obj))->ob_type), NULL((void*)0)); | ||||||||||||||||
1181 | if (descr == NULL((void*)0)) { | ||||||||||||||||
1182 | return NULL((void*)0); | ||||||||||||||||
1183 | } | ||||||||||||||||
1184 | if (descr->elsize != view->len) { | ||||||||||||||||
1185 | PyErr_SetString( | ||||||||||||||||
1186 | PyExc_RuntimeError, | ||||||||||||||||
1187 | "For the given ctypes object, neither the item size " | ||||||||||||||||
1188 | "computed from the PEP 3118 buffer format nor from " | ||||||||||||||||
1189 | "converting the type to a np.dtype matched the actual " | ||||||||||||||||
1190 | "size. This is a bug both in python and numpy"); | ||||||||||||||||
1191 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||||||||||||||
1192 | return NULL((void*)0); | ||||||||||||||||
1193 | } | ||||||||||||||||
1194 | } | ||||||||||||||||
1195 | |||||||||||||||||
1196 | if (view->shape != NULL((void*)0)) { | ||||||||||||||||
1197 | int k; | ||||||||||||||||
1198 | if (nd > NPY_MAXDIMS32 || nd < 0) { | ||||||||||||||||
1199 | PyErr_Format(PyExc_RuntimeError, | ||||||||||||||||
1200 | "PEP3118 dimensions do not satisfy 0 <= ndim <= NPY_MAXDIMS"); | ||||||||||||||||
1201 | goto fail; | ||||||||||||||||
1202 | } | ||||||||||||||||
1203 | for (k = 0; k < nd; ++k) { | ||||||||||||||||
1204 | shape[k] = view->shape[k]; | ||||||||||||||||
1205 | } | ||||||||||||||||
1206 | if (view->strides != NULL((void*)0)) { | ||||||||||||||||
1207 | for (k = 0; k < nd; ++k) { | ||||||||||||||||
1208 | strides[k] = view->strides[k]; | ||||||||||||||||
1209 | } | ||||||||||||||||
1210 | } | ||||||||||||||||
1211 | else { | ||||||||||||||||
1212 | d = view->len; | ||||||||||||||||
1213 | for (k = 0; k < nd; ++k) { | ||||||||||||||||
1214 | if (view->shape[k] != 0) { | ||||||||||||||||
1215 | d /= view->shape[k]; | ||||||||||||||||
1216 | } | ||||||||||||||||
1217 | strides[k] = d; | ||||||||||||||||
1218 | } | ||||||||||||||||
1219 | } | ||||||||||||||||
1220 | } | ||||||||||||||||
1221 | else { | ||||||||||||||||
1222 | if (nd == 1) { | ||||||||||||||||
1223 | shape[0] = view->len / view->itemsize; | ||||||||||||||||
1224 | strides[0] = view->itemsize; | ||||||||||||||||
1225 | } | ||||||||||||||||
1226 | else if (nd > 1) { | ||||||||||||||||
1227 | PyErr_SetString(PyExc_RuntimeError, | ||||||||||||||||
1228 | "ndim computed from the PEP 3118 buffer format " | ||||||||||||||||
1229 | "is greater than 1, but shape is NULL."); | ||||||||||||||||
1230 | goto fail; | ||||||||||||||||
1231 | } | ||||||||||||||||
1232 | } | ||||||||||||||||
1233 | |||||||||||||||||
1234 | flags = NPY_ARRAY_BEHAVED(0x0100 | 0x0400) & (view->readonly ? ~NPY_ARRAY_WRITEABLE0x0400 : ~0); | ||||||||||||||||
1235 | r = PyArray_NewFromDescrAndBase( | ||||||||||||||||
1236 | &PyArray_Type, descr, | ||||||||||||||||
1237 | nd, shape, strides, view->buf, | ||||||||||||||||
1238 | flags, NULL((void*)0), memoryview); | ||||||||||||||||
1239 | return r; | ||||||||||||||||
1240 | |||||||||||||||||
1241 | |||||||||||||||||
1242 | fail: | ||||||||||||||||
1243 | Py_XDECREF(r)_Py_XDECREF(((PyObject*)(r))); | ||||||||||||||||
1244 | Py_XDECREF(descr)_Py_XDECREF(((PyObject*)(descr))); | ||||||||||||||||
1245 | return NULL((void*)0); | ||||||||||||||||
1246 | |||||||||||||||||
1247 | } | ||||||||||||||||
1248 | |||||||||||||||||
1249 | |||||||||||||||||
1250 | /** | ||||||||||||||||
1251 | * Attempts to extract an array from an array-like object. | ||||||||||||||||
1252 | * | ||||||||||||||||
1253 | * array-like is defined as either | ||||||||||||||||
1254 | * | ||||||||||||||||
1255 | * * an object implementing the PEP 3118 buffer interface; | ||||||||||||||||
1256 | * * an object with __array_struct__ or __array_interface__ attributes; | ||||||||||||||||
1257 | * * an object with an __array__ function. | ||||||||||||||||
1258 | * | ||||||||||||||||
1259 | * @param op The object to convert to an array | ||||||||||||||||
1260 | * @param requested_type a requested dtype instance, may be NULL; The result | ||||||||||||||||
1261 | * DType may be used, but is not enforced. | ||||||||||||||||
1262 | * @param writeable whether the result must be writeable. | ||||||||||||||||
1263 | * @param context Unused parameter, must be NULL (should be removed later). | ||||||||||||||||
1264 | * | ||||||||||||||||
1265 | * @returns The array object, Py_NotImplemented if op is not array-like, | ||||||||||||||||
1266 | * or NULL with an error set. (A new reference to Py_NotImplemented | ||||||||||||||||
1267 | * is returned.) | ||||||||||||||||
1268 | */ | ||||||||||||||||
1269 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
1270 | _array_from_array_like(PyObject *op, | ||||||||||||||||
1271 | PyArray_Descr *requested_dtype, npy_bool writeable, PyObject *context) { | ||||||||||||||||
1272 | PyObject* tmp; | ||||||||||||||||
1273 | |||||||||||||||||
1274 | /* | ||||||||||||||||
1275 | * If op supports the PEP 3118 buffer interface. | ||||||||||||||||
1276 | * We skip bytes and unicode since they are considered scalars. Unicode | ||||||||||||||||
1277 | * would fail but bytes would be incorrectly converted to a uint8 array. | ||||||||||||||||
1278 | */ | ||||||||||||||||
1279 | if (!PyBytes_Check(op)((((((PyObject*)(op))->ob_type))->tp_flags & ((1UL << 27))) != 0) && !PyUnicode_Check(op)((((((PyObject*)(op))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | ||||||||||||||||
1280 | PyObject *memoryview = PyMemoryView_FromObject(op); | ||||||||||||||||
1281 | if (memoryview == NULL((void*)0)) { | ||||||||||||||||
1282 | PyErr_Clear(); | ||||||||||||||||
1283 | } | ||||||||||||||||
1284 | else { | ||||||||||||||||
1285 | tmp = _array_from_buffer_3118(memoryview); | ||||||||||||||||
1286 | Py_DECREF(memoryview)_Py_DECREF(((PyObject*)(memoryview))); | ||||||||||||||||
1287 | if (tmp == NULL((void*)0)) { | ||||||||||||||||
1288 | return NULL((void*)0); | ||||||||||||||||
1289 | } | ||||||||||||||||
1290 | |||||||||||||||||
1291 | if (writeable | ||||||||||||||||
1292 | && PyArray_FailUnlessWriteable( | ||||||||||||||||
1293 | (PyArrayObject *)tmp, "PEP 3118 buffer") < 0) { | ||||||||||||||||
1294 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | ||||||||||||||||
1295 | return NULL((void*)0); | ||||||||||||||||
1296 | } | ||||||||||||||||
1297 | |||||||||||||||||
1298 | return tmp; | ||||||||||||||||
1299 | } | ||||||||||||||||
1300 | } | ||||||||||||||||
1301 | |||||||||||||||||
1302 | /* | ||||||||||||||||
1303 | * If op supports the __array_struct__ or __array_interface__ interface. | ||||||||||||||||
1304 | */ | ||||||||||||||||
1305 | tmp = PyArray_FromStructInterface(op); | ||||||||||||||||
1306 | if (tmp == NULL((void*)0)) { | ||||||||||||||||
1307 | return NULL((void*)0); | ||||||||||||||||
1308 | } | ||||||||||||||||
1309 | if (tmp == Py_NotImplemented(&_Py_NotImplementedStruct)) { | ||||||||||||||||
1310 | /* Until the return, NotImplemented is always a borrowed reference*/ | ||||||||||||||||
1311 | tmp = PyArray_FromInterface(op); | ||||||||||||||||
1312 | if (tmp == NULL((void*)0)) { | ||||||||||||||||
1313 | return NULL((void*)0); | ||||||||||||||||
1314 | } | ||||||||||||||||
1315 | } | ||||||||||||||||
1316 | |||||||||||||||||
1317 | /* | ||||||||||||||||
1318 | * If op supplies the __array__ function. | ||||||||||||||||
1319 | * The documentation says this should produce a copy, so | ||||||||||||||||
1320 | * we skip this method if writeable is true, because the intent | ||||||||||||||||
1321 | * of writeable is to modify the operand. | ||||||||||||||||
1322 | * XXX: If the implementation is wrong, and/or if actual | ||||||||||||||||
1323 | * usage requires this behave differently, | ||||||||||||||||
1324 | * this should be changed! | ||||||||||||||||
1325 | */ | ||||||||||||||||
1326 | if (!writeable && tmp == Py_NotImplemented(&_Py_NotImplementedStruct)) { | ||||||||||||||||
1327 | tmp = PyArray_FromArrayAttr(op, requested_dtype, context); | ||||||||||||||||
1328 | if (tmp == NULL((void*)0)) { | ||||||||||||||||
1329 | return NULL((void*)0); | ||||||||||||||||
1330 | } | ||||||||||||||||
1331 | } | ||||||||||||||||
1332 | |||||||||||||||||
1333 | if (tmp != Py_NotImplemented(&_Py_NotImplementedStruct)) { | ||||||||||||||||
1334 | if (writeable && | ||||||||||||||||
1335 | PyArray_FailUnlessWriteable((PyArrayObject *)tmp, | ||||||||||||||||
1336 | "array interface object") < 0) { | ||||||||||||||||
1337 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | ||||||||||||||||
1338 | return NULL((void*)0); | ||||||||||||||||
1339 | } | ||||||||||||||||
1340 | return tmp; | ||||||||||||||||
1341 | } | ||||||||||||||||
1342 | |||||||||||||||||
1343 | /* Until here Py_NotImplemented was borrowed */ | ||||||||||||||||
1344 | Py_INCREF(Py_NotImplemented)_Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct)))); | ||||||||||||||||
1345 | return Py_NotImplemented(&_Py_NotImplementedStruct); | ||||||||||||||||
1346 | } | ||||||||||||||||
1347 | |||||||||||||||||
1348 | |||||||||||||||||
1349 | /*NUMPY_API*/ | ||||||||||||||||
1350 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||||||||||
1351 | PyArray_GetArrayParamsFromObject(PyObject *NPY_UNUSED(op)(__NPY_UNUSED_TAGGEDop) __attribute__ ((__unused__)), | ||||||||||||||||
1352 | PyArray_Descr *NPY_UNUSED(requested_dtype)(__NPY_UNUSED_TAGGEDrequested_dtype) __attribute__ ((__unused__ )), | ||||||||||||||||
1353 | npy_bool NPY_UNUSED(writeable)(__NPY_UNUSED_TAGGEDwriteable) __attribute__ ((__unused__)), | ||||||||||||||||
1354 | PyArray_Descr **NPY_UNUSED(out_dtype)(__NPY_UNUSED_TAGGEDout_dtype) __attribute__ ((__unused__)), | ||||||||||||||||
1355 | int *NPY_UNUSED(out_ndim)(__NPY_UNUSED_TAGGEDout_ndim) __attribute__ ((__unused__)), npy_intp *NPY_UNUSED(out_dims)(__NPY_UNUSED_TAGGEDout_dims) __attribute__ ((__unused__)), | ||||||||||||||||
1356 | PyArrayObject **NPY_UNUSED(out_arr)(__NPY_UNUSED_TAGGEDout_arr) __attribute__ ((__unused__)), PyObject *NPY_UNUSED(context)(__NPY_UNUSED_TAGGEDcontext) __attribute__ ((__unused__))) | ||||||||||||||||
1357 | { | ||||||||||||||||
1358 | /* Deprecated in NumPy 1.19, removed in NumPy 1.20. */ | ||||||||||||||||
1359 | PyErr_SetString(PyExc_RuntimeError, | ||||||||||||||||
1360 | "PyArray_GetArrayParamsFromObject() C-API function is removed " | ||||||||||||||||
1361 | "`PyArray_FromAny()` should be used at this time. New C-API " | ||||||||||||||||
1362 | "may be exposed in the future (please do request this if it " | ||||||||||||||||
1363 | "would help you)."); | ||||||||||||||||
1364 | return -1; | ||||||||||||||||
1365 | } | ||||||||||||||||
1366 | |||||||||||||||||
1367 | |||||||||||||||||
1368 | /* | ||||||||||||||||
1369 | * This function is a legacy implementation to retain subarray dtype | ||||||||||||||||
1370 | * behaviour in array coercion. The behaviour here makes sense if tuples | ||||||||||||||||
1371 | * of matching dimensionality are being coerced. Due to the difficulty | ||||||||||||||||
1372 | * that the result is ill-defined for lists of array-likes, this is deprecated. | ||||||||||||||||
1373 | * | ||||||||||||||||
1374 | * WARNING: Do not use this function, it exists purely to support a deprecated | ||||||||||||||||
1375 | * code path. | ||||||||||||||||
1376 | */ | ||||||||||||||||
1377 | static int | ||||||||||||||||
1378 | setArrayFromSequence(PyArrayObject *a, PyObject *s, | ||||||||||||||||
1379 | int dim, PyArrayObject * dst) | ||||||||||||||||
1380 | { | ||||||||||||||||
1381 | Py_ssize_t i, slen; | ||||||||||||||||
1382 | int res = -1; | ||||||||||||||||
1383 | |||||||||||||||||
1384 | /* first recursion, view equal destination */ | ||||||||||||||||
1385 | if (dst == NULL((void*)0)) | ||||||||||||||||
1386 | dst = a; | ||||||||||||||||
1387 | |||||||||||||||||
1388 | /* | ||||||||||||||||
1389 | * This code is to ensure that the sequence access below will | ||||||||||||||||
1390 | * return a lower-dimensional sequence. | ||||||||||||||||
1391 | */ | ||||||||||||||||
1392 | |||||||||||||||||
1393 | /* INCREF on entry DECREF on exit */ | ||||||||||||||||
1394 | Py_INCREF(s)_Py_INCREF(((PyObject*)(s))); | ||||||||||||||||
1395 | |||||||||||||||||
1396 | PyObject *seq = NULL((void*)0); | ||||||||||||||||
1397 | |||||||||||||||||
1398 | if (PyArray_Check(s)((((PyObject*)(s))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(s))->ob_type), (&PyArray_Type)))) { | ||||||||||||||||
1399 | if (!(PyArray_CheckExact(s)(((PyObject*)(s))->ob_type == &PyArray_Type))) { | ||||||||||||||||
1400 | /* | ||||||||||||||||
1401 | * make sure a base-class array is used so that the dimensionality | ||||||||||||||||
1402 | * reduction assumption is correct. | ||||||||||||||||
1403 | */ | ||||||||||||||||
1404 | /* This will DECREF(s) if replaced */ | ||||||||||||||||
1405 | s = PyArray_EnsureArray(s); | ||||||||||||||||
1406 | if (s == NULL((void*)0)) { | ||||||||||||||||
1407 | goto fail; | ||||||||||||||||
1408 | } | ||||||||||||||||
1409 | } | ||||||||||||||||
1410 | |||||||||||||||||
1411 | /* dst points to correct array subsection */ | ||||||||||||||||
1412 | if (PyArray_CopyInto(dst, (PyArrayObject *)s) < 0) { | ||||||||||||||||
1413 | goto fail; | ||||||||||||||||
1414 | } | ||||||||||||||||
1415 | |||||||||||||||||
1416 | Py_DECREF(s)_Py_DECREF(((PyObject*)(s))); | ||||||||||||||||
1417 | return 0; | ||||||||||||||||
1418 | } | ||||||||||||||||
1419 | |||||||||||||||||
1420 | if (dim > PyArray_NDIM(a)) { | ||||||||||||||||
1421 | PyErr_Format(PyExc_ValueError, | ||||||||||||||||
1422 | "setArrayFromSequence: sequence/array dimensions mismatch."); | ||||||||||||||||
1423 | goto fail; | ||||||||||||||||
1424 | } | ||||||||||||||||
1425 | |||||||||||||||||
1426 | /* Try __array__ before using s as a sequence */ | ||||||||||||||||
1427 | PyObject *tmp = _array_from_array_like(s, NULL((void*)0), 0, NULL((void*)0)); | ||||||||||||||||
1428 | if (tmp == NULL((void*)0)) { | ||||||||||||||||
1429 | goto fail; | ||||||||||||||||
1430 | } | ||||||||||||||||
1431 | else if (tmp == Py_NotImplemented(&_Py_NotImplementedStruct)) { | ||||||||||||||||
1432 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | ||||||||||||||||
1433 | } | ||||||||||||||||
1434 | else { | ||||||||||||||||
1435 | int r = PyArray_CopyInto(dst, (PyArrayObject *)tmp); | ||||||||||||||||
1436 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | ||||||||||||||||
1437 | if (r < 0) { | ||||||||||||||||
1438 | goto fail; | ||||||||||||||||
1439 | } | ||||||||||||||||
1440 | Py_DECREF(s)_Py_DECREF(((PyObject*)(s))); | ||||||||||||||||
1441 | return 0; | ||||||||||||||||
1442 | } | ||||||||||||||||
1443 | |||||||||||||||||
1444 | seq = PySequence_Fast(s, "Could not convert object to sequence"); | ||||||||||||||||
1445 | if (seq == NULL((void*)0)) { | ||||||||||||||||
1446 | goto fail; | ||||||||||||||||
1447 | } | ||||||||||||||||
1448 | slen = PySequence_Fast_GET_SIZE(seq)(((((((PyObject*)(seq))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? (((void) (0)), (((PyVarObject*)(seq)) ->ob_size)) : (((PyVarObject*)((((void) (0)), (PyTupleObject *)(seq))))->ob_size)); | ||||||||||||||||
1449 | |||||||||||||||||
1450 | /* | ||||||||||||||||
1451 | * Either the dimensions match, or the sequence has length 1 and can | ||||||||||||||||
1452 | * be broadcast to the destination. | ||||||||||||||||
1453 | */ | ||||||||||||||||
1454 | if (slen != PyArray_DIMS(a)[dim] && slen != 1) { | ||||||||||||||||
1455 | PyErr_Format(PyExc_ValueError, | ||||||||||||||||
1456 | "cannot copy sequence with size %zd to array axis " | ||||||||||||||||
1457 | "with dimension %" NPY_INTP_FMT"ld", slen, PyArray_DIMS(a)[dim]); | ||||||||||||||||
1458 | goto fail; | ||||||||||||||||
1459 | } | ||||||||||||||||
1460 | |||||||||||||||||
1461 | /* Broadcast the one element from the sequence to all the outputs */ | ||||||||||||||||
1462 | if (slen == 1) { | ||||||||||||||||
1463 | PyObject *o = PySequence_Fast_GET_ITEM(seq, 0)(((((((PyObject*)(seq))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? (((PyListObject *)(seq))->ob_item[ 0]) : ((((void) (0)), (PyTupleObject *)(seq))->ob_item[0]) ); | ||||||||||||||||
1464 | npy_intp alen = PyArray_DIM(a, dim); | ||||||||||||||||
1465 | |||||||||||||||||
1466 | for (i = 0; i < alen; i++) { | ||||||||||||||||
1467 | if ((PyArray_NDIM(a) - dim) > 1) { | ||||||||||||||||
1468 | PyArrayObject * tmp = | ||||||||||||||||
1469 | (PyArrayObject *)array_item_asarray(dst, i); | ||||||||||||||||
1470 | if (tmp == NULL((void*)0)) { | ||||||||||||||||
1471 | goto fail; | ||||||||||||||||
1472 | } | ||||||||||||||||
1473 | |||||||||||||||||
1474 | res = setArrayFromSequence(a, o, dim+1, tmp); | ||||||||||||||||
1475 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | ||||||||||||||||
1476 | } | ||||||||||||||||
1477 | else { | ||||||||||||||||
1478 | char * b = (PyArray_BYTES(dst) + i * PyArray_STRIDES(dst)[0]); | ||||||||||||||||
1479 | res = PyArray_SETITEM(dst, b, o); | ||||||||||||||||
1480 | } | ||||||||||||||||
1481 | if (res < 0) { | ||||||||||||||||
1482 | goto fail; | ||||||||||||||||
1483 | } | ||||||||||||||||
1484 | } | ||||||||||||||||
1485 | } | ||||||||||||||||
1486 | /* Copy element by element */ | ||||||||||||||||
1487 | else { | ||||||||||||||||
1488 | for (i = 0; i < slen; i++) { | ||||||||||||||||
1489 | PyObject * o = PySequence_Fast_GET_ITEM(seq, i)(((((((PyObject*)(seq))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? (((PyListObject *)(seq))->ob_item[ i]) : ((((void) (0)), (PyTupleObject *)(seq))->ob_item[i]) ); | ||||||||||||||||
1490 | if ((PyArray_NDIM(a) - dim) > 1) { | ||||||||||||||||
1491 | PyArrayObject * tmp = | ||||||||||||||||
1492 | (PyArrayObject *)array_item_asarray(dst, i); | ||||||||||||||||
1493 | if (tmp == NULL((void*)0)) { | ||||||||||||||||
1494 | goto fail; | ||||||||||||||||
1495 | } | ||||||||||||||||
1496 | |||||||||||||||||
1497 | res = setArrayFromSequence(a, o, dim+1, tmp); | ||||||||||||||||
1498 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | ||||||||||||||||
1499 | } | ||||||||||||||||
1500 | else { | ||||||||||||||||
1501 | char * b = (PyArray_BYTES(dst) + i * PyArray_STRIDES(dst)[0]); | ||||||||||||||||
1502 | res = PyArray_SETITEM(dst, b, o); | ||||||||||||||||
1503 | } | ||||||||||||||||
1504 | if (res < 0) { | ||||||||||||||||
1505 | goto fail; | ||||||||||||||||
1506 | } | ||||||||||||||||
1507 | } | ||||||||||||||||
1508 | } | ||||||||||||||||
1509 | |||||||||||||||||
1510 | Py_DECREF(seq)_Py_DECREF(((PyObject*)(seq))); | ||||||||||||||||
1511 | Py_DECREF(s)_Py_DECREF(((PyObject*)(s))); | ||||||||||||||||
1512 | return 0; | ||||||||||||||||
1513 | |||||||||||||||||
1514 | fail: | ||||||||||||||||
1515 | Py_XDECREF(seq)_Py_XDECREF(((PyObject*)(seq))); | ||||||||||||||||
1516 | Py_DECREF(s)_Py_DECREF(((PyObject*)(s))); | ||||||||||||||||
1517 | return res; | ||||||||||||||||
1518 | } | ||||||||||||||||
1519 | |||||||||||||||||
1520 | |||||||||||||||||
1521 | |||||||||||||||||
1522 | /*NUMPY_API | ||||||||||||||||
1523 | * Does not check for NPY_ARRAY_ENSURECOPY and NPY_ARRAY_NOTSWAPPED in flags | ||||||||||||||||
1524 | * Steals a reference to newtype --- which can be NULL | ||||||||||||||||
1525 | */ | ||||||||||||||||
1526 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
1527 | PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth, | ||||||||||||||||
1528 | int max_depth, int flags, PyObject *context) | ||||||||||||||||
1529 | { | ||||||||||||||||
1530 | /* | ||||||||||||||||
1531 | * This is the main code to make a NumPy array from a Python | ||||||||||||||||
1532 | * Object. It is called from many different places. | ||||||||||||||||
1533 | */ | ||||||||||||||||
1534 | PyArrayObject *arr = NULL((void*)0), *ret; | ||||||||||||||||
1535 | PyArray_Descr *dtype = NULL((void*)0); | ||||||||||||||||
1536 | coercion_cache_obj *cache = NULL((void*)0); | ||||||||||||||||
1537 | int ndim = 0; | ||||||||||||||||
1538 | npy_intp dims[NPY_MAXDIMS32]; | ||||||||||||||||
1539 | |||||||||||||||||
1540 | if (context
| ||||||||||||||||
1541 | PyErr_SetString(PyExc_RuntimeError, "'context' must be NULL"); | ||||||||||||||||
1542 | return NULL((void*)0); | ||||||||||||||||
1543 | } | ||||||||||||||||
1544 | |||||||||||||||||
1545 | PyArray_Descr *fixed_descriptor; | ||||||||||||||||
1546 | PyArray_DTypeMeta *fixed_DType; | ||||||||||||||||
1547 | if (PyArray_ExtractDTypeAndDescriptor((PyObject *)newtype, | ||||||||||||||||
1548 | &fixed_descriptor, &fixed_DType) < 0) { | ||||||||||||||||
1549 | Py_XDECREF(newtype)_Py_XDECREF(((PyObject*)(newtype))); | ||||||||||||||||
1550 | return NULL((void*)0); | ||||||||||||||||
1551 | } | ||||||||||||||||
1552 | Py_XDECREF(newtype)_Py_XDECREF(((PyObject*)(newtype))); | ||||||||||||||||
1553 | |||||||||||||||||
1554 | ndim = PyArray_DiscoverDTypeAndShape(op, | ||||||||||||||||
1555 | NPY_MAXDIMS32, dims, &cache, fixed_DType, fixed_descriptor, &dtype); | ||||||||||||||||
1556 | |||||||||||||||||
1557 | Py_XDECREF(fixed_descriptor)_Py_XDECREF(((PyObject*)(fixed_descriptor))); | ||||||||||||||||
1558 | Py_XDECREF(fixed_DType)_Py_XDECREF(((PyObject*)(fixed_DType))); | ||||||||||||||||
1559 | if (ndim < 0) { | ||||||||||||||||
1560 | return NULL((void*)0); | ||||||||||||||||
1561 | } | ||||||||||||||||
1562 | |||||||||||||||||
1563 | if (NPY_UNLIKELY(fixed_descriptor != NULL && PyDataType_HASSUBARRAY(dtype))__builtin_expect(!!(fixed_descriptor != ((void*)0) && ((dtype)->subarray != ((void*)0))), 0)) { | ||||||||||||||||
1564 | /* | ||||||||||||||||
1565 | * When a subarray dtype was passed in, its dimensions are appended | ||||||||||||||||
1566 | * to the array dimension (causing a dimension mismatch). | ||||||||||||||||
1567 | * There is a problem with that, because if we coerce from non-arrays | ||||||||||||||||
1568 | * we do this correctly by element (as defined by tuples), but for | ||||||||||||||||
1569 | * arrays we first append the dimensions and then assign to the base | ||||||||||||||||
1570 | * dtype and then assign which causes the problem. | ||||||||||||||||
1571 | * | ||||||||||||||||
1572 | * Thus, we check if there is an array included, in that case we | ||||||||||||||||
1573 | * give a FutureWarning. | ||||||||||||||||
1574 | * When the warning is removed, PyArray_Pack will have to ensure | ||||||||||||||||
1575 | * that that it does not append the dimensions when creating the | ||||||||||||||||
1576 | * subarrays to assign `arr[0] = obj[0]`. | ||||||||||||||||
1577 | */ | ||||||||||||||||
1578 | int includes_array = 0; | ||||||||||||||||
1579 | if (cache != NULL((void*)0)) { | ||||||||||||||||
1580 | /* This is not ideal, but it is a pretty special case */ | ||||||||||||||||
1581 | coercion_cache_obj *next = cache; | ||||||||||||||||
1582 | while (next != NULL((void*)0)) { | ||||||||||||||||
1583 | if (!next->sequence) { | ||||||||||||||||
1584 | includes_array = 1; | ||||||||||||||||
1585 | break; | ||||||||||||||||
1586 | } | ||||||||||||||||
1587 | next = next->next; | ||||||||||||||||
1588 | } | ||||||||||||||||
1589 | } | ||||||||||||||||
1590 | if (includes_array) { | ||||||||||||||||
1591 | npy_free_coercion_cache(cache); | ||||||||||||||||
1592 | |||||||||||||||||
1593 | ret = (PyArrayObject *) PyArray_NewFromDescr( | ||||||||||||||||
1594 | &PyArray_Type, dtype, ndim, dims, NULL((void*)0), NULL((void*)0), | ||||||||||||||||
1595 | flags & NPY_ARRAY_F_CONTIGUOUS0x0002, NULL((void*)0)); | ||||||||||||||||
1596 | if (ret == NULL((void*)0)) { | ||||||||||||||||
1597 | return NULL((void*)0); | ||||||||||||||||
1598 | } | ||||||||||||||||
1599 | assert(PyArray_NDIM(ret) != ndim)((void) (0)); | ||||||||||||||||
1600 | |||||||||||||||||
1601 | /* NumPy 1.20, 2020-10-01 */ | ||||||||||||||||
1602 | if (DEPRECATE_FUTUREWARNING(PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1603 | "creating an array with a subarray dtype will behave "PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1604 | "differently when the `np.array()` (or `asarray`, etc.) "PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1605 | "call includes an array or array object.\n"PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1606 | "If you are converting a single array or a list of arrays,"PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1607 | "you can opt-in to the future behaviour using:\n"PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1608 | " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n"PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1609 | " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n"PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1610 | "\n"PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1611 | "By including a new field and indexing it after the "PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1612 | "conversion.\n"PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1613 | "This may lead to a different result or to current failures "PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) | ||||||||||||||||
1614 | "succeeding. (FutureWarning since NumPy 1.20)")PyErr_WarnEx(PyExc_FutureWarning,"creating an array with a subarray dtype will behave " "differently when the `np.array()` (or `asarray`, etc.) " "call includes an array or array object.\n" "If you are converting a single array or a list of arrays," "you can opt-in to the future behaviour using:\n" " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n" " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n" "\n" "By including a new field and indexing it after the " "conversion.\n" "This may lead to a different result or to current failures " "succeeding. (FutureWarning since NumPy 1.20)",1) < 0) { | ||||||||||||||||
1615 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
1616 | return NULL((void*)0); | ||||||||||||||||
1617 | } | ||||||||||||||||
1618 | |||||||||||||||||
1619 | if (setArrayFromSequence(ret, op, 0, NULL((void*)0)) < 0) { | ||||||||||||||||
1620 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
1621 | return NULL((void*)0); | ||||||||||||||||
1622 | } | ||||||||||||||||
1623 | return (PyObject *)ret; | ||||||||||||||||
1624 | } | ||||||||||||||||
1625 | } | ||||||||||||||||
1626 | |||||||||||||||||
1627 | if (dtype == NULL((void*)0)) { | ||||||||||||||||
1628 | dtype = PyArray_DescrFromType(NPY_DEFAULT_TYPENPY_DOUBLE); | ||||||||||||||||
1629 | } | ||||||||||||||||
1630 | |||||||||||||||||
1631 | if (min_depth
| ||||||||||||||||
1632 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
1633 | "object of too small depth for desired array"); | ||||||||||||||||
1634 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
1635 | npy_free_coercion_cache(cache); | ||||||||||||||||
1636 | return NULL((void*)0); | ||||||||||||||||
1637 | } | ||||||||||||||||
1638 | if (max_depth
| ||||||||||||||||
1639 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
1640 | "object too deep for desired array"); | ||||||||||||||||
1641 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
1642 | npy_free_coercion_cache(cache); | ||||||||||||||||
1643 | return NULL((void*)0); | ||||||||||||||||
1644 | } | ||||||||||||||||
1645 | |||||||||||||||||
1646 | /* Got the correct parameters, but the cache may already hold the result */ | ||||||||||||||||
1647 | if (cache != NULL((void*)0) && !(cache->sequence)) { | ||||||||||||||||
1648 | /* | ||||||||||||||||
1649 | * There is only a single array-like and it was converted, it | ||||||||||||||||
1650 | * may still have the incorrect type, but that is handled below. | ||||||||||||||||
1651 | */ | ||||||||||||||||
1652 | assert(cache->converted_obj == op)((void) (0)); | ||||||||||||||||
1653 | arr = (PyArrayObject *)(cache->arr_or_sequence); | ||||||||||||||||
1654 | /* we may need to cast or assert flags (e.g. copy) */ | ||||||||||||||||
1655 | PyObject *res = PyArray_FromArray(arr, dtype, flags); | ||||||||||||||||
1656 | npy_unlink_coercion_cache(cache); | ||||||||||||||||
1657 | return res; | ||||||||||||||||
1658 | } | ||||||||||||||||
1659 | else if (cache
) || PyType_IsSubtype((((PyObject*)(op))->ob_type), (& PyVoidArrType_Type)))) && | ||||||||||||||||
1660 | !(((PyVoidScalarObject *)op)->flags & NPY_ARRAY_OWNDATA0x0004) && | ||||||||||||||||
1661 | newtype == NULL((void*)0)) { | ||||||||||||||||
1662 | /* | ||||||||||||||||
1663 | * Special case, we return a *view* into void scalars, mainly to | ||||||||||||||||
1664 | * allow things similar to the "reversed" assignment: | ||||||||||||||||
1665 | * arr[indx]["field"] = val # instead of arr["field"][indx] = val | ||||||||||||||||
1666 | * | ||||||||||||||||
1667 | * It is unclear that this is necessary in this particular code path. | ||||||||||||||||
1668 | * Note that this path is only activated when the user did _not_ | ||||||||||||||||
1669 | * provide a dtype (newtype is NULL). | ||||||||||||||||
1670 | */ | ||||||||||||||||
1671 | assert(ndim == 0)((void) (0)); | ||||||||||||||||
1672 | |||||||||||||||||
1673 | return PyArray_NewFromDescrAndBase( | ||||||||||||||||
1674 | &PyArray_Type, dtype, | ||||||||||||||||
1675 | 0, NULL((void*)0), NULL((void*)0), | ||||||||||||||||
1676 | ((PyVoidScalarObject *)op)->obval, | ||||||||||||||||
1677 | ((PyVoidScalarObject *)op)->flags, | ||||||||||||||||
1678 | NULL((void*)0), op); | ||||||||||||||||
1679 | } | ||||||||||||||||
1680 | else if (cache
| ||||||||||||||||
1681 | PyDataType_ISSIGNED(newtype)(((((PyArray_Descr*)(newtype))->type_num) == NPY_BYTE) || ( (((PyArray_Descr*)(newtype))->type_num) == NPY_SHORT) || ( (((PyArray_Descr*)(newtype))->type_num) == NPY_INT) || ((( (PyArray_Descr*)(newtype))->type_num) == NPY_LONG) || (((( PyArray_Descr*)(newtype))->type_num) == NPY_LONGLONG)) && PyArray_IsScalar(op, Generic)(((((PyObject*)(op))->ob_type) == (&PyGenericArrType_Type ) || PyType_IsSubtype((((PyObject*)(op))->ob_type), (& PyGenericArrType_Type))))) { | ||||||||||||||||
| |||||||||||||||||
1682 | assert(ndim == 0)((void) (0)); | ||||||||||||||||
1683 | /* | ||||||||||||||||
1684 | * This is an (possible) inconsistency where: | ||||||||||||||||
1685 | * | ||||||||||||||||
1686 | * np.array(np.float64(np.nan), dtype=np.int64) | ||||||||||||||||
1687 | * | ||||||||||||||||
1688 | * behaves differently from: | ||||||||||||||||
1689 | * | ||||||||||||||||
1690 | * np.array([np.float64(np.nan)], dtype=np.int64) | ||||||||||||||||
1691 | * arr1d_int64[0] = np.float64(np.nan) | ||||||||||||||||
1692 | * np.array(np.array(np.nan), dtype=np.int64) | ||||||||||||||||
1693 | * | ||||||||||||||||
1694 | * by not raising an error instead of using typical casting. | ||||||||||||||||
1695 | * The error is desirable, but to always error seems like a | ||||||||||||||||
1696 | * larger change to be considered at some other time and it is | ||||||||||||||||
1697 | * undesirable that 0-D arrays behave differently from scalars. | ||||||||||||||||
1698 | * This retains the behaviour, largely due to issues in pandas | ||||||||||||||||
1699 | * which relied on a try/except (although hopefully that will | ||||||||||||||||
1700 | * have a better solution at some point): | ||||||||||||||||
1701 | * https://github.com/pandas-dev/pandas/issues/35481 | ||||||||||||||||
1702 | */ | ||||||||||||||||
1703 | return PyArray_FromScalar(op, dtype); | ||||||||||||||||
1704 | } | ||||||||||||||||
1705 | |||||||||||||||||
1706 | /* There was no array (or array-like) passed in directly. */ | ||||||||||||||||
1707 | if ((flags & NPY_ARRAY_WRITEBACKIFCOPY0x2000) || | ||||||||||||||||
1708 | (flags & NPY_ARRAY_UPDATEIFCOPY0x1000)) { | ||||||||||||||||
1709 | PyErr_SetString(PyExc_TypeError, | ||||||||||||||||
1710 | "WRITEBACKIFCOPY used for non-array input."); | ||||||||||||||||
1711 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
1712 | npy_free_coercion_cache(cache); | ||||||||||||||||
1713 | return NULL((void*)0); | ||||||||||||||||
1714 | } | ||||||||||||||||
1715 | |||||||||||||||||
1716 | /* Create a new array and copy the data */ | ||||||||||||||||
1717 | Py_INCREF(dtype)_Py_INCREF(((PyObject*)(dtype))); /* hold on in case of a subarray that is replaced */ | ||||||||||||||||
1718 | ret = (PyArrayObject *)PyArray_NewFromDescr( | ||||||||||||||||
1719 | &PyArray_Type, dtype, ndim, dims, NULL((void*)0), NULL((void*)0), | ||||||||||||||||
1720 | flags&NPY_ARRAY_F_CONTIGUOUS0x0002, NULL((void*)0)); | ||||||||||||||||
1721 | if (ret == NULL((void*)0)) { | ||||||||||||||||
1722 | npy_free_coercion_cache(cache); | ||||||||||||||||
1723 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
1724 | return NULL((void*)0); | ||||||||||||||||
1725 | } | ||||||||||||||||
1726 | if (ndim == PyArray_NDIM(ret)) { | ||||||||||||||||
1727 | /* | ||||||||||||||||
1728 | * Appending of dimensions did not occur, so use the actual dtype | ||||||||||||||||
1729 | * below. This is relevant for S0 or U0 which can be replaced with | ||||||||||||||||
1730 | * S1 or U1, although that should likely change. | ||||||||||||||||
1731 | */ | ||||||||||||||||
1732 | Py_SETREF(dtype, PyArray_DESCR(ret))do { PyObject *_py_tmp = ((PyObject*)(dtype)); (dtype) = (PyArray_DESCR (ret)); _Py_DECREF(((PyObject*)(_py_tmp))); } while (0); | ||||||||||||||||
1733 | Py_INCREF(dtype)_Py_INCREF(((PyObject*)(dtype))); | ||||||||||||||||
1734 | } | ||||||||||||||||
1735 | |||||||||||||||||
1736 | if (cache == NULL((void*)0)) { | ||||||||||||||||
1737 | /* This is a single item. Set it directly. */ | ||||||||||||||||
1738 | assert(ndim == 0)((void) (0)); | ||||||||||||||||
1739 | |||||||||||||||||
1740 | if (PyArray_Pack(dtype, PyArray_BYTES(ret), op) < 0) { | ||||||||||||||||
1741 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
1742 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
1743 | return NULL((void*)0); | ||||||||||||||||
1744 | } | ||||||||||||||||
1745 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
1746 | return (PyObject *)ret; | ||||||||||||||||
1747 | } | ||||||||||||||||
1748 | assert(ndim != 0)((void) (0)); | ||||||||||||||||
1749 | assert(op == cache->converted_obj)((void) (0)); | ||||||||||||||||
1750 | |||||||||||||||||
1751 | /* Decrease the number of dimensions to the detected ones */ | ||||||||||||||||
1752 | int out_ndim = PyArray_NDIM(ret); | ||||||||||||||||
1753 | PyArray_Descr *out_descr = PyArray_DESCR(ret); | ||||||||||||||||
1754 | ((PyArrayObject_fields *)ret)->nd = ndim; | ||||||||||||||||
1755 | ((PyArrayObject_fields *)ret)->descr = dtype; | ||||||||||||||||
1756 | |||||||||||||||||
1757 | int success = PyArray_AssignFromCache(ret, cache); | ||||||||||||||||
1758 | |||||||||||||||||
1759 | ((PyArrayObject_fields *)ret)->nd = out_ndim; | ||||||||||||||||
1760 | ((PyArrayObject_fields *)ret)->descr = out_descr; | ||||||||||||||||
1761 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
1762 | if (success < 0) { | ||||||||||||||||
1763 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
1764 | return NULL((void*)0); | ||||||||||||||||
1765 | } | ||||||||||||||||
1766 | return (PyObject *)ret; | ||||||||||||||||
1767 | } | ||||||||||||||||
1768 | |||||||||||||||||
1769 | /* | ||||||||||||||||
1770 | * flags is any of | ||||||||||||||||
1771 | * NPY_ARRAY_C_CONTIGUOUS (formerly CONTIGUOUS), | ||||||||||||||||
1772 | * NPY_ARRAY_F_CONTIGUOUS (formerly FORTRAN), | ||||||||||||||||
1773 | * NPY_ARRAY_ALIGNED, | ||||||||||||||||
1774 | * NPY_ARRAY_WRITEABLE, | ||||||||||||||||
1775 | * NPY_ARRAY_NOTSWAPPED, | ||||||||||||||||
1776 | * NPY_ARRAY_ENSURECOPY, | ||||||||||||||||
1777 | * NPY_ARRAY_UPDATEIFCOPY, | ||||||||||||||||
1778 | * NPY_ARRAY_WRITEBACKIFCOPY, | ||||||||||||||||
1779 | * NPY_ARRAY_FORCECAST, | ||||||||||||||||
1780 | * NPY_ARRAY_ENSUREARRAY, | ||||||||||||||||
1781 | * NPY_ARRAY_ELEMENTSTRIDES | ||||||||||||||||
1782 | * | ||||||||||||||||
1783 | * or'd (|) together | ||||||||||||||||
1784 | * | ||||||||||||||||
1785 | * Any of these flags present means that the returned array should | ||||||||||||||||
1786 | * guarantee that aspect of the array. Otherwise the returned array | ||||||||||||||||
1787 | * won't guarantee it -- it will depend on the object as to whether or | ||||||||||||||||
1788 | * not it has such features. | ||||||||||||||||
1789 | * | ||||||||||||||||
1790 | * Note that NPY_ARRAY_ENSURECOPY is enough | ||||||||||||||||
1791 | * to guarantee NPY_ARRAY_C_CONTIGUOUS, NPY_ARRAY_ALIGNED and | ||||||||||||||||
1792 | * NPY_ARRAY_WRITEABLE and therefore it is redundant to include | ||||||||||||||||
1793 | * those as well. | ||||||||||||||||
1794 | * | ||||||||||||||||
1795 | * NPY_ARRAY_BEHAVED == NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEABLE | ||||||||||||||||
1796 | * NPY_ARRAY_CARRAY = NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_BEHAVED | ||||||||||||||||
1797 | * NPY_ARRAY_FARRAY = NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_BEHAVED | ||||||||||||||||
1798 | * | ||||||||||||||||
1799 | * NPY_ARRAY_F_CONTIGUOUS can be set in the FLAGS to request a FORTRAN array. | ||||||||||||||||
1800 | * Fortran arrays are always behaved (aligned, | ||||||||||||||||
1801 | * notswapped, and writeable) and not (C) CONTIGUOUS (if > 1d). | ||||||||||||||||
1802 | * | ||||||||||||||||
1803 | * NPY_ARRAY_UPDATEIFCOPY is deprecated in favor of | ||||||||||||||||
1804 | * NPY_ARRAY_WRITEBACKIFCOPY in 1.14 | ||||||||||||||||
1805 | |||||||||||||||||
1806 | * NPY_ARRAY_WRITEBACKIFCOPY flag sets this flag in the returned | ||||||||||||||||
1807 | * array if a copy is made and the base argument points to the (possibly) | ||||||||||||||||
1808 | * misbehaved array. Before returning to python, PyArray_ResolveWritebackIfCopy | ||||||||||||||||
1809 | * must be called to update the contents of the original array from the copy. | ||||||||||||||||
1810 | * | ||||||||||||||||
1811 | * NPY_ARRAY_FORCECAST will cause a cast to occur regardless of whether or not | ||||||||||||||||
1812 | * it is safe. | ||||||||||||||||
1813 | * | ||||||||||||||||
1814 | * context is passed through to PyArray_GetArrayParamsFromObject | ||||||||||||||||
1815 | */ | ||||||||||||||||
1816 | |||||||||||||||||
1817 | /*NUMPY_API | ||||||||||||||||
1818 | * steals a reference to descr -- accepts NULL | ||||||||||||||||
1819 | */ | ||||||||||||||||
1820 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
1821 | PyArray_CheckFromAny(PyObject *op, PyArray_Descr *descr, int min_depth, | ||||||||||||||||
1822 | int max_depth, int requires, PyObject *context) | ||||||||||||||||
1823 | { | ||||||||||||||||
1824 | PyObject *obj; | ||||||||||||||||
1825 | if (requires & NPY_ARRAY_NOTSWAPPED0x0200) { | ||||||||||||||||
1826 | if (!descr && PyArray_Check(op)((((PyObject*)(op))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(op))->ob_type), (&PyArray_Type))) && | ||||||||||||||||
1827 | PyArray_ISBYTESWAPPED((PyArrayObject* )op)(!((PyArray_DESCR((PyArrayObject* )op)->byteorder) != '>' ))) { | ||||||||||||||||
1828 | descr = PyArray_DescrNew(PyArray_DESCR((PyArrayObject *)op)); | ||||||||||||||||
1829 | } | ||||||||||||||||
1830 | else if (descr && !PyArray_ISNBO(descr->byteorder)((descr->byteorder) != '>')) { | ||||||||||||||||
1831 | PyArray_DESCR_REPLACE(descr)do { PyArray_Descr *_new_; _new_ = PyArray_DescrNew(descr); _Py_XDECREF (((PyObject*)(descr))); descr = _new_; } while(0); | ||||||||||||||||
1832 | } | ||||||||||||||||
1833 | if (descr && descr->byteorder != NPY_IGNORE'|') { | ||||||||||||||||
1834 | descr->byteorder = NPY_NATIVE'='; | ||||||||||||||||
1835 | } | ||||||||||||||||
1836 | } | ||||||||||||||||
1837 | |||||||||||||||||
1838 | obj = PyArray_FromAny(op, descr, min_depth, max_depth, requires, context); | ||||||||||||||||
1839 | if (obj == NULL((void*)0)) { | ||||||||||||||||
1840 | return NULL((void*)0); | ||||||||||||||||
1841 | } | ||||||||||||||||
1842 | if ((requires & NPY_ARRAY_ELEMENTSTRIDES0x0080) && | ||||||||||||||||
1843 | !PyArray_ElementStrides(obj)) { | ||||||||||||||||
1844 | PyObject *ret; | ||||||||||||||||
1845 | ret = PyArray_NewCopy((PyArrayObject *)obj, NPY_ANYORDER); | ||||||||||||||||
1846 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | ||||||||||||||||
1847 | obj = ret; | ||||||||||||||||
1848 | } | ||||||||||||||||
1849 | return obj; | ||||||||||||||||
1850 | } | ||||||||||||||||
1851 | |||||||||||||||||
1852 | |||||||||||||||||
1853 | /*NUMPY_API | ||||||||||||||||
1854 | * steals reference to newtype --- acc. NULL | ||||||||||||||||
1855 | */ | ||||||||||||||||
1856 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
1857 | PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags) | ||||||||||||||||
1858 | { | ||||||||||||||||
1859 | |||||||||||||||||
1860 | PyArrayObject *ret = NULL((void*)0); | ||||||||||||||||
1861 | int copy = 0; | ||||||||||||||||
1862 | int arrflags; | ||||||||||||||||
1863 | PyArray_Descr *oldtype; | ||||||||||||||||
1864 | NPY_CASTING casting = NPY_SAFE_CASTING; | ||||||||||||||||
1865 | |||||||||||||||||
1866 | oldtype = PyArray_DESCR(arr); | ||||||||||||||||
1867 | if (newtype == NULL((void*)0)) { | ||||||||||||||||
1868 | /* | ||||||||||||||||
1869 | * Check if object is of array with Null newtype. | ||||||||||||||||
1870 | * If so return it directly instead of checking for casting. | ||||||||||||||||
1871 | */ | ||||||||||||||||
1872 | if (flags == 0) { | ||||||||||||||||
1873 | Py_INCREF(arr)_Py_INCREF(((PyObject*)(arr))); | ||||||||||||||||
1874 | return (PyObject *)arr; | ||||||||||||||||
1875 | } | ||||||||||||||||
1876 | newtype = oldtype; | ||||||||||||||||
1877 | Py_INCREF(oldtype)_Py_INCREF(((PyObject*)(oldtype))); | ||||||||||||||||
1878 | } | ||||||||||||||||
1879 | else if (PyDataType_ISUNSIZED(newtype)((newtype)->elsize == 0 && !(((PyArray_Descr *)(newtype ))->names != ((void*)0)))) { | ||||||||||||||||
1880 | PyArray_DESCR_REPLACE(newtype)do { PyArray_Descr *_new_; _new_ = PyArray_DescrNew(newtype); _Py_XDECREF(((PyObject*)(newtype))); newtype = _new_; } while (0); | ||||||||||||||||
1881 | if (newtype == NULL((void*)0)) { | ||||||||||||||||
1882 | return NULL((void*)0); | ||||||||||||||||
1883 | } | ||||||||||||||||
1884 | newtype->elsize = oldtype->elsize; | ||||||||||||||||
1885 | } | ||||||||||||||||
1886 | |||||||||||||||||
1887 | /* If the casting if forced, use the 'unsafe' casting rule */ | ||||||||||||||||
1888 | if (flags & NPY_ARRAY_FORCECAST0x0010) { | ||||||||||||||||
1889 | casting = NPY_UNSAFE_CASTING; | ||||||||||||||||
1890 | } | ||||||||||||||||
1891 | |||||||||||||||||
1892 | /* Raise an error if the casting rule isn't followed */ | ||||||||||||||||
1893 | if (!PyArray_CanCastArrayTo(arr, newtype, casting)) { | ||||||||||||||||
1894 | PyErr_Clear(); | ||||||||||||||||
1895 | npy_set_invalid_cast_error( | ||||||||||||||||
1896 | PyArray_DESCR(arr), newtype, casting, PyArray_NDIM(arr) == 0); | ||||||||||||||||
1897 | Py_DECREF(newtype)_Py_DECREF(((PyObject*)(newtype))); | ||||||||||||||||
1898 | return NULL((void*)0); | ||||||||||||||||
1899 | } | ||||||||||||||||
1900 | |||||||||||||||||
1901 | arrflags = PyArray_FLAGS(arr); | ||||||||||||||||
1902 | /* If a guaranteed copy was requested */ | ||||||||||||||||
1903 | copy = (flags & NPY_ARRAY_ENSURECOPY0x0020) || | ||||||||||||||||
1904 | /* If C contiguous was requested, and arr is not */ | ||||||||||||||||
1905 | ((flags & NPY_ARRAY_C_CONTIGUOUS0x0001) && | ||||||||||||||||
1906 | (!(arrflags & NPY_ARRAY_C_CONTIGUOUS0x0001))) || | ||||||||||||||||
1907 | /* If an aligned array was requested, and arr is not */ | ||||||||||||||||
1908 | ((flags & NPY_ARRAY_ALIGNED0x0100) && | ||||||||||||||||
1909 | (!(arrflags & NPY_ARRAY_ALIGNED0x0100))) || | ||||||||||||||||
1910 | /* If a Fortran contiguous array was requested, and arr is not */ | ||||||||||||||||
1911 | ((flags & NPY_ARRAY_F_CONTIGUOUS0x0002) && | ||||||||||||||||
1912 | (!(arrflags & NPY_ARRAY_F_CONTIGUOUS0x0002))) || | ||||||||||||||||
1913 | /* If a writeable array was requested, and arr is not */ | ||||||||||||||||
1914 | ((flags & NPY_ARRAY_WRITEABLE0x0400) && | ||||||||||||||||
1915 | (!(arrflags & NPY_ARRAY_WRITEABLE0x0400))) || | ||||||||||||||||
1916 | !PyArray_EquivTypes(oldtype, newtype); | ||||||||||||||||
1917 | |||||||||||||||||
1918 | if (copy) { | ||||||||||||||||
1919 | NPY_ORDER order = NPY_KEEPORDER; | ||||||||||||||||
1920 | int subok = 1; | ||||||||||||||||
1921 | |||||||||||||||||
1922 | /* Set the order for the copy being made based on the flags */ | ||||||||||||||||
1923 | if (flags & NPY_ARRAY_F_CONTIGUOUS0x0002) { | ||||||||||||||||
1924 | order = NPY_FORTRANORDER; | ||||||||||||||||
1925 | } | ||||||||||||||||
1926 | else if (flags & NPY_ARRAY_C_CONTIGUOUS0x0001) { | ||||||||||||||||
1927 | order = NPY_CORDER; | ||||||||||||||||
1928 | } | ||||||||||||||||
1929 | |||||||||||||||||
1930 | if ((flags & NPY_ARRAY_ENSUREARRAY0x0040)) { | ||||||||||||||||
1931 | subok = 0; | ||||||||||||||||
1932 | } | ||||||||||||||||
1933 | ret = (PyArrayObject *)PyArray_NewLikeArray(arr, order, | ||||||||||||||||
1934 | newtype, subok); | ||||||||||||||||
1935 | if (ret == NULL((void*)0)) { | ||||||||||||||||
1936 | return NULL((void*)0); | ||||||||||||||||
1937 | } | ||||||||||||||||
1938 | |||||||||||||||||
1939 | if (PyArray_CopyInto(ret, arr) < 0) { | ||||||||||||||||
1940 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
1941 | return NULL((void*)0); | ||||||||||||||||
1942 | } | ||||||||||||||||
1943 | |||||||||||||||||
1944 | if (flags & NPY_ARRAY_UPDATEIFCOPY0x1000) { | ||||||||||||||||
1945 | /* This is the ONLY place the NPY_ARRAY_UPDATEIFCOPY flag | ||||||||||||||||
1946 | * is still used. | ||||||||||||||||
1947 | * Can be deleted once the flag itself is removed | ||||||||||||||||
1948 | */ | ||||||||||||||||
1949 | |||||||||||||||||
1950 | /* 2017-Nov-10 1.14 */ | ||||||||||||||||
1951 | if (DEPRECATE(PyErr_WarnEx(PyExc_DeprecationWarning,"NPY_ARRAY_UPDATEIFCOPY, NPY_ARRAY_INOUT_ARRAY, and " "NPY_ARRAY_INOUT_FARRAY are deprecated, use NPY_WRITEBACKIFCOPY, " "NPY_ARRAY_INOUT_ARRAY2, or NPY_ARRAY_INOUT_FARRAY2 respectively " "instead, and call PyArray_ResolveWritebackIfCopy before the " "array is deallocated, i.e. before the last call to Py_DECREF." ,1) | ||||||||||||||||
1952 | "NPY_ARRAY_UPDATEIFCOPY, NPY_ARRAY_INOUT_ARRAY, and "PyErr_WarnEx(PyExc_DeprecationWarning,"NPY_ARRAY_UPDATEIFCOPY, NPY_ARRAY_INOUT_ARRAY, and " "NPY_ARRAY_INOUT_FARRAY are deprecated, use NPY_WRITEBACKIFCOPY, " "NPY_ARRAY_INOUT_ARRAY2, or NPY_ARRAY_INOUT_FARRAY2 respectively " "instead, and call PyArray_ResolveWritebackIfCopy before the " "array is deallocated, i.e. before the last call to Py_DECREF." ,1) | ||||||||||||||||
1953 | "NPY_ARRAY_INOUT_FARRAY are deprecated, use NPY_WRITEBACKIFCOPY, "PyErr_WarnEx(PyExc_DeprecationWarning,"NPY_ARRAY_UPDATEIFCOPY, NPY_ARRAY_INOUT_ARRAY, and " "NPY_ARRAY_INOUT_FARRAY are deprecated, use NPY_WRITEBACKIFCOPY, " "NPY_ARRAY_INOUT_ARRAY2, or NPY_ARRAY_INOUT_FARRAY2 respectively " "instead, and call PyArray_ResolveWritebackIfCopy before the " "array is deallocated, i.e. before the last call to Py_DECREF." ,1) | ||||||||||||||||
1954 | "NPY_ARRAY_INOUT_ARRAY2, or NPY_ARRAY_INOUT_FARRAY2 respectively "PyErr_WarnEx(PyExc_DeprecationWarning,"NPY_ARRAY_UPDATEIFCOPY, NPY_ARRAY_INOUT_ARRAY, and " "NPY_ARRAY_INOUT_FARRAY are deprecated, use NPY_WRITEBACKIFCOPY, " "NPY_ARRAY_INOUT_ARRAY2, or NPY_ARRAY_INOUT_FARRAY2 respectively " "instead, and call PyArray_ResolveWritebackIfCopy before the " "array is deallocated, i.e. before the last call to Py_DECREF." ,1) | ||||||||||||||||
1955 | "instead, and call PyArray_ResolveWritebackIfCopy before the "PyErr_WarnEx(PyExc_DeprecationWarning,"NPY_ARRAY_UPDATEIFCOPY, NPY_ARRAY_INOUT_ARRAY, and " "NPY_ARRAY_INOUT_FARRAY are deprecated, use NPY_WRITEBACKIFCOPY, " "NPY_ARRAY_INOUT_ARRAY2, or NPY_ARRAY_INOUT_FARRAY2 respectively " "instead, and call PyArray_ResolveWritebackIfCopy before the " "array is deallocated, i.e. before the last call to Py_DECREF." ,1) | ||||||||||||||||
1956 | "array is deallocated, i.e. before the last call to Py_DECREF.")PyErr_WarnEx(PyExc_DeprecationWarning,"NPY_ARRAY_UPDATEIFCOPY, NPY_ARRAY_INOUT_ARRAY, and " "NPY_ARRAY_INOUT_FARRAY are deprecated, use NPY_WRITEBACKIFCOPY, " "NPY_ARRAY_INOUT_ARRAY2, or NPY_ARRAY_INOUT_FARRAY2 respectively " "instead, and call PyArray_ResolveWritebackIfCopy before the " "array is deallocated, i.e. before the last call to Py_DECREF." ,1) < 0) { | ||||||||||||||||
1957 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
1958 | return NULL((void*)0); | ||||||||||||||||
1959 | } | ||||||||||||||||
1960 | Py_INCREF(arr)_Py_INCREF(((PyObject*)(arr))); | ||||||||||||||||
1961 | if (PyArray_SetWritebackIfCopyBase(ret, arr) < 0) { | ||||||||||||||||
1962 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
1963 | return NULL((void*)0); | ||||||||||||||||
1964 | } | ||||||||||||||||
1965 | PyArray_ENABLEFLAGS(ret, NPY_ARRAY_UPDATEIFCOPY0x1000); | ||||||||||||||||
1966 | PyArray_CLEARFLAGS(ret, NPY_ARRAY_WRITEBACKIFCOPY0x2000); | ||||||||||||||||
1967 | } | ||||||||||||||||
1968 | else if (flags & NPY_ARRAY_WRITEBACKIFCOPY0x2000) { | ||||||||||||||||
1969 | Py_INCREF(arr)_Py_INCREF(((PyObject*)(arr))); | ||||||||||||||||
1970 | if (PyArray_SetWritebackIfCopyBase(ret, arr) < 0) { | ||||||||||||||||
1971 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
1972 | return NULL((void*)0); | ||||||||||||||||
1973 | } | ||||||||||||||||
1974 | } | ||||||||||||||||
1975 | } | ||||||||||||||||
1976 | /* | ||||||||||||||||
1977 | * If no copy then take an appropriate view if necessary, or | ||||||||||||||||
1978 | * just return a reference to ret itself. | ||||||||||||||||
1979 | */ | ||||||||||||||||
1980 | else { | ||||||||||||||||
1981 | int needview = ((flags & NPY_ARRAY_ENSUREARRAY0x0040) && | ||||||||||||||||
1982 | !PyArray_CheckExact(arr)(((PyObject*)(arr))->ob_type == &PyArray_Type)); | ||||||||||||||||
1983 | |||||||||||||||||
1984 | Py_DECREF(newtype)_Py_DECREF(((PyObject*)(newtype))); | ||||||||||||||||
1985 | if (needview) { | ||||||||||||||||
1986 | PyTypeObject *subtype = NULL((void*)0); | ||||||||||||||||
1987 | |||||||||||||||||
1988 | if (flags & NPY_ARRAY_ENSUREARRAY0x0040) { | ||||||||||||||||
1989 | subtype = &PyArray_Type; | ||||||||||||||||
1990 | } | ||||||||||||||||
1991 | |||||||||||||||||
1992 | ret = (PyArrayObject *)PyArray_View(arr, NULL((void*)0), subtype); | ||||||||||||||||
1993 | if (ret == NULL((void*)0)) { | ||||||||||||||||
1994 | return NULL((void*)0); | ||||||||||||||||
1995 | } | ||||||||||||||||
1996 | } | ||||||||||||||||
1997 | else { | ||||||||||||||||
1998 | Py_INCREF(arr)_Py_INCREF(((PyObject*)(arr))); | ||||||||||||||||
1999 | ret = arr; | ||||||||||||||||
2000 | } | ||||||||||||||||
2001 | } | ||||||||||||||||
2002 | |||||||||||||||||
2003 | return (PyObject *)ret; | ||||||||||||||||
2004 | } | ||||||||||||||||
2005 | |||||||||||||||||
2006 | /*NUMPY_API */ | ||||||||||||||||
2007 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
2008 | PyArray_FromStructInterface(PyObject *input) | ||||||||||||||||
2009 | { | ||||||||||||||||
2010 | PyArray_Descr *thetype = NULL((void*)0); | ||||||||||||||||
2011 | PyArrayInterface *inter; | ||||||||||||||||
2012 | PyObject *attr; | ||||||||||||||||
2013 | char endian = NPY_NATBYTE'<'; | ||||||||||||||||
2014 | |||||||||||||||||
2015 | attr = PyArray_LookupSpecial_OnInstance(input, "__array_struct__"); | ||||||||||||||||
2016 | if (attr == NULL((void*)0)) { | ||||||||||||||||
2017 | if (PyErr_Occurred()) { | ||||||||||||||||
2018 | return NULL((void*)0); | ||||||||||||||||
2019 | } else { | ||||||||||||||||
2020 | return Py_NotImplemented(&_Py_NotImplementedStruct); | ||||||||||||||||
2021 | } | ||||||||||||||||
2022 | } | ||||||||||||||||
2023 | if (!PyCapsule_CheckExact(attr)((((PyObject*)(attr))->ob_type) == &PyCapsule_Type)) { | ||||||||||||||||
2024 | if (PyType_Check(input)((((((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 31))) != 0) && PyObject_HasAttrString(attr, "__get__")) { | ||||||||||||||||
2025 | /* | ||||||||||||||||
2026 | * If the input is a class `attr` should be a property-like object. | ||||||||||||||||
2027 | * This cannot be interpreted as an array, but is a valid. | ||||||||||||||||
2028 | * (Needed due to the lookup being on the instance rather than type) | ||||||||||||||||
2029 | */ | ||||||||||||||||
2030 | Py_DECREF(attr)_Py_DECREF(((PyObject*)(attr))); | ||||||||||||||||
2031 | return Py_NotImplemented(&_Py_NotImplementedStruct); | ||||||||||||||||
2032 | } | ||||||||||||||||
2033 | goto fail; | ||||||||||||||||
2034 | } | ||||||||||||||||
2035 | inter = PyCapsule_GetPointer(attr, NULL((void*)0)); | ||||||||||||||||
2036 | if (inter == NULL((void*)0)) { | ||||||||||||||||
2037 | goto fail; | ||||||||||||||||
2038 | } | ||||||||||||||||
2039 | if (inter->two != 2) { | ||||||||||||||||
2040 | goto fail; | ||||||||||||||||
2041 | } | ||||||||||||||||
2042 | if ((inter->flags & NPY_ARRAY_NOTSWAPPED0x0200) != NPY_ARRAY_NOTSWAPPED0x0200) { | ||||||||||||||||
2043 | endian = NPY_OPPBYTE'>'; | ||||||||||||||||
2044 | inter->flags &= ~NPY_ARRAY_NOTSWAPPED0x0200; | ||||||||||||||||
2045 | } | ||||||||||||||||
2046 | |||||||||||||||||
2047 | if (inter->flags & NPY_ARR_HAS_DESCR0x0800) { | ||||||||||||||||
2048 | if (PyArray_DescrConverter(inter->descr, &thetype) == NPY_FAIL0) { | ||||||||||||||||
2049 | thetype = NULL((void*)0); | ||||||||||||||||
2050 | PyErr_Clear(); | ||||||||||||||||
2051 | } | ||||||||||||||||
2052 | } | ||||||||||||||||
2053 | |||||||||||||||||
2054 | if (thetype == NULL((void*)0)) { | ||||||||||||||||
2055 | PyObject *type_str = PyUnicode_FromFormat( | ||||||||||||||||
2056 | "%c%c%d", endian, inter->typekind, inter->itemsize); | ||||||||||||||||
2057 | if (type_str == NULL((void*)0)) { | ||||||||||||||||
2058 | Py_DECREF(attr)_Py_DECREF(((PyObject*)(attr))); | ||||||||||||||||
2059 | return NULL((void*)0); | ||||||||||||||||
2060 | } | ||||||||||||||||
2061 | int ok = PyArray_DescrConverter(type_str, &thetype); | ||||||||||||||||
2062 | Py_DECREF(type_str)_Py_DECREF(((PyObject*)(type_str))); | ||||||||||||||||
2063 | if (ok != NPY_SUCCEED1) { | ||||||||||||||||
2064 | Py_DECREF(attr)_Py_DECREF(((PyObject*)(attr))); | ||||||||||||||||
2065 | return NULL((void*)0); | ||||||||||||||||
2066 | } | ||||||||||||||||
2067 | } | ||||||||||||||||
2068 | |||||||||||||||||
2069 | PyObject *ret = PyArray_NewFromDescrAndBase( | ||||||||||||||||
2070 | &PyArray_Type, thetype, | ||||||||||||||||
2071 | inter->nd, inter->shape, inter->strides, inter->data, | ||||||||||||||||
2072 | inter->flags, NULL((void*)0), input); | ||||||||||||||||
2073 | Py_DECREF(attr)_Py_DECREF(((PyObject*)(attr))); | ||||||||||||||||
2074 | return ret; | ||||||||||||||||
2075 | |||||||||||||||||
2076 | fail: | ||||||||||||||||
2077 | PyErr_SetString(PyExc_ValueError, "invalid __array_struct__"); | ||||||||||||||||
2078 | Py_DECREF(attr)_Py_DECREF(((PyObject*)(attr))); | ||||||||||||||||
2079 | return NULL((void*)0); | ||||||||||||||||
2080 | } | ||||||||||||||||
2081 | |||||||||||||||||
2082 | /* | ||||||||||||||||
2083 | * Checks if the object in descr is the default 'descr' member for the | ||||||||||||||||
2084 | * __array_interface__ dictionary with 'typestr' member typestr. | ||||||||||||||||
2085 | */ | ||||||||||||||||
2086 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||||||||||
2087 | _is_default_descr(PyObject *descr, PyObject *typestr) { | ||||||||||||||||
2088 | if (!PyList_Check(descr)((((((PyObject*)(descr))->ob_type))->tp_flags & ((1UL << 25))) != 0) || PyList_GET_SIZE(descr)(((void) (0)), (((PyVarObject*)(descr))->ob_size)) != 1) { | ||||||||||||||||
2089 | return 0; | ||||||||||||||||
2090 | } | ||||||||||||||||
2091 | PyObject *tuple = PyList_GET_ITEM(descr, 0)(((PyListObject *)(descr))->ob_item[0]); | ||||||||||||||||
2092 | if (!(PyTuple_Check(tuple)((((((PyObject*)(tuple))->ob_type))->tp_flags & ((1UL << 26))) != 0) && PyTuple_GET_SIZE(tuple)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(tuple))))-> ob_size) == 2)) { | ||||||||||||||||
2093 | return 0; | ||||||||||||||||
2094 | } | ||||||||||||||||
2095 | PyObject *name = PyTuple_GET_ITEM(tuple, 0)((((void) (0)), (PyTupleObject *)(tuple))->ob_item[0]); | ||||||||||||||||
2096 | if (!(PyUnicode_Check(name)((((((PyObject*)(name))->ob_type))->tp_flags & ((1UL << 28))) != 0) && PyUnicode_GetLength(name) == 0)) { | ||||||||||||||||
2097 | return 0; | ||||||||||||||||
2098 | } | ||||||||||||||||
2099 | PyObject *typestr2 = PyTuple_GET_ITEM(tuple, 1)((((void) (0)), (PyTupleObject *)(tuple))->ob_item[1]); | ||||||||||||||||
2100 | return PyObject_RichCompareBool(typestr, typestr2, Py_EQ2); | ||||||||||||||||
2101 | } | ||||||||||||||||
2102 | |||||||||||||||||
2103 | |||||||||||||||||
2104 | /* | ||||||||||||||||
2105 | * A helper function to transition away from ignoring errors during | ||||||||||||||||
2106 | * special attribute lookups during array coercion. | ||||||||||||||||
2107 | */ | ||||||||||||||||
2108 | static NPY_INLINEinline int | ||||||||||||||||
2109 | deprecated_lookup_error_clearing(PyTypeObject *type, char *attribute) | ||||||||||||||||
2110 | { | ||||||||||||||||
2111 | PyObject *exc_type, *exc_value, *traceback; | ||||||||||||||||
2112 | PyErr_Fetch(&exc_type, &exc_value, &traceback); | ||||||||||||||||
2113 | |||||||||||||||||
2114 | /* DEPRECATED 2021-05-12, NumPy 1.21. */ | ||||||||||||||||
2115 | int res = PyErr_WarnFormat(PyExc_DeprecationWarning, 1, | ||||||||||||||||
2116 | "An exception was ignored while fetching the attribute `%s` from " | ||||||||||||||||
2117 | "an object of type '%s'. With the exception of `AttributeError` " | ||||||||||||||||
2118 | "NumPy will always raise this exception in the future. Raise this " | ||||||||||||||||
2119 | "deprecation warning to see the original exception. " | ||||||||||||||||
2120 | "(Warning added NumPy 1.21)", attribute, type->tp_name); | ||||||||||||||||
2121 | |||||||||||||||||
2122 | if (res < 0) { | ||||||||||||||||
2123 | npy_PyErr_ChainExceptionsCause(exc_type, exc_value, traceback); | ||||||||||||||||
2124 | return -1; | ||||||||||||||||
2125 | } | ||||||||||||||||
2126 | else { | ||||||||||||||||
2127 | /* `PyErr_Fetch` cleared the original error, delete the references */ | ||||||||||||||||
2128 | Py_DECREF(exc_type)_Py_DECREF(((PyObject*)(exc_type))); | ||||||||||||||||
2129 | Py_XDECREF(exc_value)_Py_XDECREF(((PyObject*)(exc_value))); | ||||||||||||||||
2130 | Py_XDECREF(traceback)_Py_XDECREF(((PyObject*)(traceback))); | ||||||||||||||||
2131 | return 0; | ||||||||||||||||
2132 | } | ||||||||||||||||
2133 | } | ||||||||||||||||
2134 | |||||||||||||||||
2135 | |||||||||||||||||
2136 | /*NUMPY_API*/ | ||||||||||||||||
2137 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
2138 | PyArray_FromInterface(PyObject *origin) | ||||||||||||||||
2139 | { | ||||||||||||||||
2140 | PyObject *iface = NULL((void*)0); | ||||||||||||||||
2141 | PyObject *attr = NULL((void*)0); | ||||||||||||||||
2142 | PyObject *base = NULL((void*)0); | ||||||||||||||||
2143 | PyArrayObject *ret; | ||||||||||||||||
2144 | PyArray_Descr *dtype = NULL((void*)0); | ||||||||||||||||
2145 | char *data = NULL((void*)0); | ||||||||||||||||
2146 | Py_buffer view; | ||||||||||||||||
2147 | int i, n; | ||||||||||||||||
2148 | npy_intp dims[NPY_MAXDIMS32], strides[NPY_MAXDIMS32]; | ||||||||||||||||
2149 | int dataflags = NPY_ARRAY_BEHAVED(0x0100 | 0x0400); | ||||||||||||||||
2150 | |||||||||||||||||
2151 | iface = PyArray_LookupSpecial_OnInstance(origin, "__array_interface__"); | ||||||||||||||||
2152 | |||||||||||||||||
2153 | if (iface == NULL((void*)0)) { | ||||||||||||||||
2154 | if (PyErr_Occurred()) { | ||||||||||||||||
2155 | if (PyErr_ExceptionMatches(PyExc_RecursionError) || | ||||||||||||||||
2156 | PyErr_ExceptionMatches(PyExc_MemoryError)) { | ||||||||||||||||
2157 | /* RecursionError and MemoryError are considered fatal */ | ||||||||||||||||
2158 | return NULL((void*)0); | ||||||||||||||||
2159 | } | ||||||||||||||||
2160 | if (deprecated_lookup_error_clearing( | ||||||||||||||||
2161 | Py_TYPE(origin)(((PyObject*)(origin))->ob_type), "__array_interface__") < 0) { | ||||||||||||||||
2162 | return NULL((void*)0); | ||||||||||||||||
2163 | } | ||||||||||||||||
2164 | } | ||||||||||||||||
2165 | return Py_NotImplemented(&_Py_NotImplementedStruct); | ||||||||||||||||
2166 | } | ||||||||||||||||
2167 | if (!PyDict_Check(iface)((((((PyObject*)(iface))->ob_type))->tp_flags & ((1UL << 29))) != 0)) { | ||||||||||||||||
2168 | if (PyType_Check(origin)((((((PyObject*)(origin))->ob_type))->tp_flags & (( 1UL << 31))) != 0) && PyObject_HasAttrString(iface, "__get__")) { | ||||||||||||||||
2169 | /* | ||||||||||||||||
2170 | * If the input is a class `iface` should be a property-like object. | ||||||||||||||||
2171 | * This cannot be interpreted as an array, but is a valid. | ||||||||||||||||
2172 | * (Needed due to the lookup being on the instance rather than type) | ||||||||||||||||
2173 | */ | ||||||||||||||||
2174 | Py_DECREF(iface)_Py_DECREF(((PyObject*)(iface))); | ||||||||||||||||
2175 | return Py_NotImplemented(&_Py_NotImplementedStruct); | ||||||||||||||||
2176 | } | ||||||||||||||||
2177 | |||||||||||||||||
2178 | Py_DECREF(iface)_Py_DECREF(((PyObject*)(iface))); | ||||||||||||||||
2179 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
2180 | "Invalid __array_interface__ value, must be a dict"); | ||||||||||||||||
2181 | return NULL((void*)0); | ||||||||||||||||
2182 | } | ||||||||||||||||
2183 | |||||||||||||||||
2184 | /* Get type string from interface specification */ | ||||||||||||||||
2185 | attr = _PyDict_GetItemStringWithError(iface, "typestr"); | ||||||||||||||||
2186 | if (attr == NULL((void*)0)) { | ||||||||||||||||
2187 | Py_DECREF(iface)_Py_DECREF(((PyObject*)(iface))); | ||||||||||||||||
2188 | if (!PyErr_Occurred()) { | ||||||||||||||||
2189 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
2190 | "Missing __array_interface__ typestr"); | ||||||||||||||||
2191 | } | ||||||||||||||||
2192 | return NULL((void*)0); | ||||||||||||||||
2193 | } | ||||||||||||||||
2194 | |||||||||||||||||
2195 | /* allow bytes for backwards compatibility */ | ||||||||||||||||
2196 | if (!PyBytes_Check(attr)((((((PyObject*)(attr))->ob_type))->tp_flags & ((1UL << 27))) != 0) && !PyUnicode_Check(attr)((((((PyObject*)(attr))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | ||||||||||||||||
2197 | PyErr_SetString(PyExc_TypeError, | ||||||||||||||||
2198 | "__array_interface__ typestr must be a string"); | ||||||||||||||||
2199 | goto fail; | ||||||||||||||||
2200 | } | ||||||||||||||||
2201 | |||||||||||||||||
2202 | /* Get dtype from type string */ | ||||||||||||||||
2203 | if (PyArray_DescrConverter(attr, &dtype) != NPY_SUCCEED1) { | ||||||||||||||||
2204 | goto fail; | ||||||||||||||||
2205 | } | ||||||||||||||||
2206 | |||||||||||||||||
2207 | /* | ||||||||||||||||
2208 | * If the dtype is NPY_VOID, see if there is extra information in | ||||||||||||||||
2209 | * the 'descr' attribute. | ||||||||||||||||
2210 | */ | ||||||||||||||||
2211 | if (dtype->type_num == NPY_VOID) { | ||||||||||||||||
2212 | PyObject *descr = _PyDict_GetItemStringWithError(iface, "descr"); | ||||||||||||||||
2213 | if (descr == NULL((void*)0) && PyErr_Occurred()) { | ||||||||||||||||
2214 | goto fail; | ||||||||||||||||
2215 | } | ||||||||||||||||
2216 | PyArray_Descr *new_dtype = NULL((void*)0); | ||||||||||||||||
2217 | if (descr != NULL((void*)0)) { | ||||||||||||||||
2218 | int is_default = _is_default_descr(descr, attr); | ||||||||||||||||
2219 | if (is_default < 0) { | ||||||||||||||||
2220 | goto fail; | ||||||||||||||||
2221 | } | ||||||||||||||||
2222 | if (!is_default) { | ||||||||||||||||
2223 | if (PyArray_DescrConverter2(descr, &new_dtype) != NPY_SUCCEED1) { | ||||||||||||||||
2224 | goto fail; | ||||||||||||||||
2225 | } | ||||||||||||||||
2226 | if (new_dtype != NULL((void*)0)) { | ||||||||||||||||
2227 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
2228 | dtype = new_dtype; | ||||||||||||||||
2229 | } | ||||||||||||||||
2230 | } | ||||||||||||||||
2231 | |||||||||||||||||
2232 | } | ||||||||||||||||
2233 | |||||||||||||||||
2234 | } | ||||||||||||||||
2235 | |||||||||||||||||
2236 | /* Get shape tuple from interface specification */ | ||||||||||||||||
2237 | attr = _PyDict_GetItemStringWithError(iface, "shape"); | ||||||||||||||||
2238 | if (attr == NULL((void*)0)) { | ||||||||||||||||
2239 | if (PyErr_Occurred()) { | ||||||||||||||||
2240 | return NULL((void*)0); | ||||||||||||||||
2241 | } | ||||||||||||||||
2242 | /* Shape must be specified when 'data' is specified */ | ||||||||||||||||
2243 | PyObject *data = _PyDict_GetItemStringWithError(iface, "data"); | ||||||||||||||||
2244 | if (data == NULL((void*)0) && PyErr_Occurred()) { | ||||||||||||||||
2245 | return NULL((void*)0); | ||||||||||||||||
2246 | } | ||||||||||||||||
2247 | else if (data != NULL((void*)0)) { | ||||||||||||||||
2248 | Py_DECREF(iface)_Py_DECREF(((PyObject*)(iface))); | ||||||||||||||||
2249 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
2250 | "Missing __array_interface__ shape"); | ||||||||||||||||
2251 | return NULL((void*)0); | ||||||||||||||||
2252 | } | ||||||||||||||||
2253 | /* Assume shape as scalar otherwise */ | ||||||||||||||||
2254 | else { | ||||||||||||||||
2255 | /* NOTE: pointers to data and base should be NULL */ | ||||||||||||||||
2256 | n = dims[0] = 0; | ||||||||||||||||
2257 | } | ||||||||||||||||
2258 | } | ||||||||||||||||
2259 | /* Make sure 'shape' is a tuple */ | ||||||||||||||||
2260 | else if (!PyTuple_Check(attr)((((((PyObject*)(attr))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | ||||||||||||||||
2261 | PyErr_SetString(PyExc_TypeError, | ||||||||||||||||
2262 | "shape must be a tuple"); | ||||||||||||||||
2263 | goto fail; | ||||||||||||||||
2264 | } | ||||||||||||||||
2265 | /* Get dimensions from shape tuple */ | ||||||||||||||||
2266 | else { | ||||||||||||||||
2267 | n = PyTuple_GET_SIZE(attr)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(attr))))-> ob_size); | ||||||||||||||||
2268 | for (i = 0; i < n; i++) { | ||||||||||||||||
2269 | PyObject *tmp = PyTuple_GET_ITEM(attr, i)((((void) (0)), (PyTupleObject *)(attr))->ob_item[i]); | ||||||||||||||||
2270 | dims[i] = PyArray_PyIntAsIntp(tmp); | ||||||||||||||||
2271 | if (error_converting(dims[i])(((dims[i]) == -1) && PyErr_Occurred())) { | ||||||||||||||||
2272 | goto fail; | ||||||||||||||||
2273 | } | ||||||||||||||||
2274 | } | ||||||||||||||||
2275 | } | ||||||||||||||||
2276 | |||||||||||||||||
2277 | /* Get data buffer from interface specification */ | ||||||||||||||||
2278 | attr = _PyDict_GetItemStringWithError(iface, "data"); | ||||||||||||||||
2279 | if (attr == NULL((void*)0) && PyErr_Occurred()){ | ||||||||||||||||
2280 | return NULL((void*)0); | ||||||||||||||||
2281 | } | ||||||||||||||||
2282 | |||||||||||||||||
2283 | /* Case for data access through pointer */ | ||||||||||||||||
2284 | if (attr && PyTuple_Check(attr)((((((PyObject*)(attr))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | ||||||||||||||||
2285 | PyObject *dataptr; | ||||||||||||||||
2286 | if (PyTuple_GET_SIZE(attr)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(attr))))-> ob_size) != 2) { | ||||||||||||||||
2287 | PyErr_SetString(PyExc_TypeError, | ||||||||||||||||
2288 | "__array_interface__ data must be a 2-tuple with " | ||||||||||||||||
2289 | "(data pointer integer, read-only flag)"); | ||||||||||||||||
2290 | goto fail; | ||||||||||||||||
2291 | } | ||||||||||||||||
2292 | dataptr = PyTuple_GET_ITEM(attr, 0)((((void) (0)), (PyTupleObject *)(attr))->ob_item[0]); | ||||||||||||||||
2293 | if (PyLong_Check(dataptr)((((((PyObject*)(dataptr))->ob_type))->tp_flags & ( (1UL << 24))) != 0)) { | ||||||||||||||||
2294 | data = PyLong_AsVoidPtr(dataptr); | ||||||||||||||||
2295 | if (data == NULL((void*)0) && PyErr_Occurred()) { | ||||||||||||||||
2296 | goto fail; | ||||||||||||||||
2297 | } | ||||||||||||||||
2298 | } | ||||||||||||||||
2299 | else { | ||||||||||||||||
2300 | PyErr_SetString(PyExc_TypeError, | ||||||||||||||||
2301 | "first element of __array_interface__ data tuple " | ||||||||||||||||
2302 | "must be an integer."); | ||||||||||||||||
2303 | goto fail; | ||||||||||||||||
2304 | } | ||||||||||||||||
2305 | if (PyObject_IsTrue(PyTuple_GET_ITEM(attr,1)((((void) (0)), (PyTupleObject *)(attr))->ob_item[1]))) { | ||||||||||||||||
2306 | dataflags &= ~NPY_ARRAY_WRITEABLE0x0400; | ||||||||||||||||
2307 | } | ||||||||||||||||
2308 | base = origin; | ||||||||||||||||
2309 | } | ||||||||||||||||
2310 | |||||||||||||||||
2311 | /* Case for data access through buffer */ | ||||||||||||||||
2312 | else if (attr) { | ||||||||||||||||
2313 | if (attr != Py_None(&_Py_NoneStruct)) { | ||||||||||||||||
2314 | base = attr; | ||||||||||||||||
2315 | } | ||||||||||||||||
2316 | else { | ||||||||||||||||
2317 | base = origin; | ||||||||||||||||
2318 | } | ||||||||||||||||
2319 | if (PyObject_GetBuffer(base, &view, | ||||||||||||||||
2320 | PyBUF_WRITABLE0x0001|PyBUF_SIMPLE0) < 0) { | ||||||||||||||||
2321 | PyErr_Clear(); | ||||||||||||||||
2322 | if (PyObject_GetBuffer(base, &view, | ||||||||||||||||
2323 | PyBUF_SIMPLE0) < 0) { | ||||||||||||||||
2324 | goto fail; | ||||||||||||||||
2325 | } | ||||||||||||||||
2326 | dataflags &= ~NPY_ARRAY_WRITEABLE0x0400; | ||||||||||||||||
2327 | } | ||||||||||||||||
2328 | data = (char *)view.buf; | ||||||||||||||||
2329 | /* | ||||||||||||||||
2330 | * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and | ||||||||||||||||
2331 | * PyObject_AsReadBuffer that this code replaces release the buffer. It is | ||||||||||||||||
2332 | * up to the object that supplies the buffer to guarantee that the buffer | ||||||||||||||||
2333 | * sticks around after the release. | ||||||||||||||||
2334 | */ | ||||||||||||||||
2335 | PyBuffer_Release(&view); | ||||||||||||||||
2336 | |||||||||||||||||
2337 | /* Get offset number from interface specification */ | ||||||||||||||||
2338 | attr = _PyDict_GetItemStringWithError(iface, "offset"); | ||||||||||||||||
2339 | if (attr == NULL((void*)0) && PyErr_Occurred()) { | ||||||||||||||||
2340 | goto fail; | ||||||||||||||||
2341 | } | ||||||||||||||||
2342 | else if (attr) { | ||||||||||||||||
2343 | npy_longlong num = PyLong_AsLongLong(attr); | ||||||||||||||||
2344 | if (error_converting(num)(((num) == -1) && PyErr_Occurred())) { | ||||||||||||||||
2345 | PyErr_SetString(PyExc_TypeError, | ||||||||||||||||
2346 | "__array_interface__ offset must be an integer"); | ||||||||||||||||
2347 | goto fail; | ||||||||||||||||
2348 | } | ||||||||||||||||
2349 | data += num; | ||||||||||||||||
2350 | } | ||||||||||||||||
2351 | } | ||||||||||||||||
2352 | |||||||||||||||||
2353 | ret = (PyArrayObject *)PyArray_NewFromDescrAndBase( | ||||||||||||||||
2354 | &PyArray_Type, dtype, | ||||||||||||||||
2355 | n, dims, NULL((void*)0), data, | ||||||||||||||||
2356 | dataflags, NULL((void*)0), base); | ||||||||||||||||
2357 | /* | ||||||||||||||||
2358 | * Ref to dtype was stolen by PyArray_NewFromDescrAndBase | ||||||||||||||||
2359 | * Prevent DECREFing dtype in fail codepath by setting to NULL | ||||||||||||||||
2360 | */ | ||||||||||||||||
2361 | dtype = NULL((void*)0); | ||||||||||||||||
2362 | if (ret == NULL((void*)0)) { | ||||||||||||||||
2363 | goto fail; | ||||||||||||||||
2364 | } | ||||||||||||||||
2365 | if (data == NULL((void*)0)) { | ||||||||||||||||
2366 | if (PyArray_SIZE(ret)PyArray_MultiplyList(PyArray_DIMS(ret), PyArray_NDIM(ret)) > 1) { | ||||||||||||||||
2367 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
2368 | "cannot coerce scalar to array with size > 1"); | ||||||||||||||||
2369 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
2370 | goto fail; | ||||||||||||||||
2371 | } | ||||||||||||||||
2372 | if (PyArray_SETITEM(ret, PyArray_DATA(ret), origin) < 0) { | ||||||||||||||||
2373 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
2374 | goto fail; | ||||||||||||||||
2375 | } | ||||||||||||||||
2376 | } | ||||||||||||||||
2377 | attr = _PyDict_GetItemStringWithError(iface, "strides"); | ||||||||||||||||
2378 | if (attr == NULL((void*)0) && PyErr_Occurred()){ | ||||||||||||||||
2379 | return NULL((void*)0); | ||||||||||||||||
2380 | } | ||||||||||||||||
2381 | if (attr != NULL((void*)0) && attr != Py_None(&_Py_NoneStruct)) { | ||||||||||||||||
2382 | if (!PyTuple_Check(attr)((((((PyObject*)(attr))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | ||||||||||||||||
2383 | PyErr_SetString(PyExc_TypeError, | ||||||||||||||||
2384 | "strides must be a tuple"); | ||||||||||||||||
2385 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
2386 | goto fail; | ||||||||||||||||
2387 | } | ||||||||||||||||
2388 | if (n != PyTuple_GET_SIZE(attr)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(attr))))-> ob_size)) { | ||||||||||||||||
2389 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
2390 | "mismatch in length of strides and shape"); | ||||||||||||||||
2391 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
2392 | goto fail; | ||||||||||||||||
2393 | } | ||||||||||||||||
2394 | for (i = 0; i < n; i++) { | ||||||||||||||||
2395 | PyObject *tmp = PyTuple_GET_ITEM(attr, i)((((void) (0)), (PyTupleObject *)(attr))->ob_item[i]); | ||||||||||||||||
2396 | strides[i] = PyArray_PyIntAsIntp(tmp); | ||||||||||||||||
2397 | if (error_converting(strides[i])(((strides[i]) == -1) && PyErr_Occurred())) { | ||||||||||||||||
2398 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
2399 | goto fail; | ||||||||||||||||
2400 | } | ||||||||||||||||
2401 | } | ||||||||||||||||
2402 | if (n) { | ||||||||||||||||
2403 | memcpy(PyArray_STRIDES(ret), strides, n*sizeof(npy_intp)); | ||||||||||||||||
2404 | } | ||||||||||||||||
2405 | } | ||||||||||||||||
2406 | PyArray_UpdateFlags(ret, NPY_ARRAY_UPDATE_ALL(0x0001 | 0x0002 | 0x0100)); | ||||||||||||||||
2407 | Py_DECREF(iface)_Py_DECREF(((PyObject*)(iface))); | ||||||||||||||||
2408 | return (PyObject *)ret; | ||||||||||||||||
2409 | |||||||||||||||||
2410 | fail: | ||||||||||||||||
2411 | Py_XDECREF(dtype)_Py_XDECREF(((PyObject*)(dtype))); | ||||||||||||||||
2412 | Py_XDECREF(iface)_Py_XDECREF(((PyObject*)(iface))); | ||||||||||||||||
2413 | return NULL((void*)0); | ||||||||||||||||
2414 | } | ||||||||||||||||
2415 | |||||||||||||||||
2416 | /*NUMPY_API | ||||||||||||||||
2417 | */ | ||||||||||||||||
2418 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
2419 | PyArray_FromArrayAttr(PyObject *op, PyArray_Descr *typecode, PyObject *context) | ||||||||||||||||
2420 | { | ||||||||||||||||
2421 | PyObject *new; | ||||||||||||||||
2422 | PyObject *array_meth; | ||||||||||||||||
2423 | |||||||||||||||||
2424 | if (context != NULL((void*)0)) { | ||||||||||||||||
2425 | PyErr_SetString(PyExc_RuntimeError, "'context' must be NULL"); | ||||||||||||||||
2426 | return NULL((void*)0); | ||||||||||||||||
2427 | } | ||||||||||||||||
2428 | array_meth = PyArray_LookupSpecial_OnInstance(op, "__array__"); | ||||||||||||||||
2429 | if (array_meth == NULL((void*)0)) { | ||||||||||||||||
2430 | if (PyErr_Occurred()) { | ||||||||||||||||
2431 | if (PyErr_ExceptionMatches(PyExc_RecursionError) || | ||||||||||||||||
2432 | PyErr_ExceptionMatches(PyExc_MemoryError)) { | ||||||||||||||||
2433 | /* RecursionError and MemoryError are considered fatal */ | ||||||||||||||||
2434 | return NULL((void*)0); | ||||||||||||||||
2435 | } | ||||||||||||||||
2436 | if (deprecated_lookup_error_clearing( | ||||||||||||||||
2437 | Py_TYPE(op)(((PyObject*)(op))->ob_type), "__array__") < 0) { | ||||||||||||||||
2438 | return NULL((void*)0); | ||||||||||||||||
2439 | } | ||||||||||||||||
2440 | } | ||||||||||||||||
2441 | return Py_NotImplemented(&_Py_NotImplementedStruct); | ||||||||||||||||
2442 | } | ||||||||||||||||
2443 | if (PyType_Check(op)((((((PyObject*)(op))->ob_type))->tp_flags & ((1UL << 31))) != 0) && PyObject_HasAttrString(array_meth, "__get__")) { | ||||||||||||||||
2444 | /* | ||||||||||||||||
2445 | * If the input is a class `array_meth` may be a property-like object. | ||||||||||||||||
2446 | * This cannot be interpreted as an array (called), but is a valid. | ||||||||||||||||
2447 | * Trying `array_meth.__call__()` on this should not be useful. | ||||||||||||||||
2448 | * (Needed due to the lookup being on the instance rather than type) | ||||||||||||||||
2449 | */ | ||||||||||||||||
2450 | Py_DECREF(array_meth)_Py_DECREF(((PyObject*)(array_meth))); | ||||||||||||||||
2451 | return Py_NotImplemented(&_Py_NotImplementedStruct); | ||||||||||||||||
2452 | } | ||||||||||||||||
2453 | if (typecode == NULL((void*)0)) { | ||||||||||||||||
2454 | new = PyObject_CallFunction_PyObject_CallFunction_SizeT(array_meth, NULL((void*)0)); | ||||||||||||||||
2455 | } | ||||||||||||||||
2456 | else { | ||||||||||||||||
2457 | new = PyObject_CallFunction_PyObject_CallFunction_SizeT(array_meth, "O", typecode); | ||||||||||||||||
2458 | } | ||||||||||||||||
2459 | Py_DECREF(array_meth)_Py_DECREF(((PyObject*)(array_meth))); | ||||||||||||||||
2460 | if (new == NULL((void*)0)) { | ||||||||||||||||
2461 | return NULL((void*)0); | ||||||||||||||||
2462 | } | ||||||||||||||||
2463 | if (!PyArray_Check(new)((((PyObject*)(new))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(new))->ob_type), (&PyArray_Type)))) { | ||||||||||||||||
2464 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
2465 | "object __array__ method not " \ | ||||||||||||||||
2466 | "producing an array"); | ||||||||||||||||
2467 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | ||||||||||||||||
2468 | return NULL((void*)0); | ||||||||||||||||
2469 | } | ||||||||||||||||
2470 | return new; | ||||||||||||||||
2471 | } | ||||||||||||||||
2472 | |||||||||||||||||
2473 | /*NUMPY_API | ||||||||||||||||
2474 | * new reference -- accepts NULL for mintype | ||||||||||||||||
2475 | */ | ||||||||||||||||
2476 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArray_Descr * | ||||||||||||||||
2477 | PyArray_DescrFromObject(PyObject *op, PyArray_Descr *mintype) | ||||||||||||||||
2478 | { | ||||||||||||||||
2479 | PyArray_Descr *dtype; | ||||||||||||||||
2480 | |||||||||||||||||
2481 | dtype = mintype; | ||||||||||||||||
2482 | Py_XINCREF(dtype)_Py_XINCREF(((PyObject*)(dtype))); | ||||||||||||||||
2483 | |||||||||||||||||
2484 | if (PyArray_DTypeFromObject(op, NPY_MAXDIMS32, &dtype) < 0) { | ||||||||||||||||
2485 | return NULL((void*)0); | ||||||||||||||||
2486 | } | ||||||||||||||||
2487 | |||||||||||||||||
2488 | if (dtype == NULL((void*)0)) { | ||||||||||||||||
2489 | return PyArray_DescrFromType(NPY_DEFAULT_TYPENPY_DOUBLE); | ||||||||||||||||
2490 | } | ||||||||||||||||
2491 | else { | ||||||||||||||||
2492 | return dtype; | ||||||||||||||||
2493 | } | ||||||||||||||||
2494 | } | ||||||||||||||||
2495 | |||||||||||||||||
2496 | /* These are also old calls (should use PyArray_NewFromDescr) */ | ||||||||||||||||
2497 | |||||||||||||||||
2498 | /* They all zero-out the memory as previously done */ | ||||||||||||||||
2499 | |||||||||||||||||
2500 | /* steals reference to descr -- and enforces native byteorder on it.*/ | ||||||||||||||||
2501 | |||||||||||||||||
2502 | /*NUMPY_API | ||||||||||||||||
2503 | Deprecated, use PyArray_NewFromDescr instead. | ||||||||||||||||
2504 | */ | ||||||||||||||||
2505 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
2506 | PyArray_FromDimsAndDataAndDescr(int NPY_UNUSED(nd)(__NPY_UNUSED_TAGGEDnd) __attribute__ ((__unused__)), int *NPY_UNUSED(d)(__NPY_UNUSED_TAGGEDd) __attribute__ ((__unused__)), | ||||||||||||||||
2507 | PyArray_Descr *descr, | ||||||||||||||||
2508 | char *NPY_UNUSED(data)(__NPY_UNUSED_TAGGEDdata) __attribute__ ((__unused__))) | ||||||||||||||||
2509 | { | ||||||||||||||||
2510 | PyErr_SetString(PyExc_NotImplementedError, | ||||||||||||||||
2511 | "PyArray_FromDimsAndDataAndDescr: use PyArray_NewFromDescr."); | ||||||||||||||||
2512 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||||||||||||||
2513 | return NULL((void*)0); | ||||||||||||||||
2514 | } | ||||||||||||||||
2515 | |||||||||||||||||
2516 | /*NUMPY_API | ||||||||||||||||
2517 | Deprecated, use PyArray_SimpleNew instead. | ||||||||||||||||
2518 | */ | ||||||||||||||||
2519 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
2520 | PyArray_FromDims(int NPY_UNUSED(nd)(__NPY_UNUSED_TAGGEDnd) __attribute__ ((__unused__)), int *NPY_UNUSED(d)(__NPY_UNUSED_TAGGEDd) __attribute__ ((__unused__)), int NPY_UNUSED(type)(__NPY_UNUSED_TAGGEDtype) __attribute__ ((__unused__))) | ||||||||||||||||
2521 | { | ||||||||||||||||
2522 | PyErr_SetString(PyExc_NotImplementedError, | ||||||||||||||||
2523 | "PyArray_FromDims: use PyArray_SimpleNew."); | ||||||||||||||||
2524 | return NULL((void*)0); | ||||||||||||||||
2525 | } | ||||||||||||||||
2526 | |||||||||||||||||
2527 | /* end old calls */ | ||||||||||||||||
2528 | |||||||||||||||||
2529 | /*NUMPY_API | ||||||||||||||||
2530 | * This is a quick wrapper around | ||||||||||||||||
2531 | * PyArray_FromAny(op, NULL, 0, 0, NPY_ARRAY_ENSUREARRAY, NULL) | ||||||||||||||||
2532 | * that special cases Arrays and PyArray_Scalars up front | ||||||||||||||||
2533 | * It *steals a reference* to the object | ||||||||||||||||
2534 | * It also guarantees that the result is PyArray_Type | ||||||||||||||||
2535 | * Because it decrefs op if any conversion needs to take place | ||||||||||||||||
2536 | * so it can be used like PyArray_EnsureArray(some_function(...)) | ||||||||||||||||
2537 | */ | ||||||||||||||||
2538 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
2539 | PyArray_EnsureArray(PyObject *op) | ||||||||||||||||
2540 | { | ||||||||||||||||
2541 | PyObject *new; | ||||||||||||||||
2542 | |||||||||||||||||
2543 | if ((op == NULL((void*)0)) || (PyArray_CheckExact(op)(((PyObject*)(op))->ob_type == &PyArray_Type))) { | ||||||||||||||||
2544 | new = op; | ||||||||||||||||
2545 | Py_XINCREF(new)_Py_XINCREF(((PyObject*)(new))); | ||||||||||||||||
2546 | } | ||||||||||||||||
2547 | else if (PyArray_Check(op)((((PyObject*)(op))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(op))->ob_type), (&PyArray_Type)))) { | ||||||||||||||||
2548 | new = PyArray_View((PyArrayObject *)op, NULL((void*)0), &PyArray_Type); | ||||||||||||||||
2549 | } | ||||||||||||||||
2550 | else if (PyArray_IsScalar(op, Generic)(((((PyObject*)(op))->ob_type) == (&PyGenericArrType_Type ) || PyType_IsSubtype((((PyObject*)(op))->ob_type), (& PyGenericArrType_Type))))) { | ||||||||||||||||
2551 | new = PyArray_FromScalar(op, NULL((void*)0)); | ||||||||||||||||
2552 | } | ||||||||||||||||
2553 | else { | ||||||||||||||||
2554 | new = PyArray_FROM_OF(op, NPY_ARRAY_ENSUREARRAY)PyArray_CheckFromAny(op, ((void*)0), 0, 0, 0x0040, ((void*)0) ); | ||||||||||||||||
2555 | } | ||||||||||||||||
2556 | Py_XDECREF(op)_Py_XDECREF(((PyObject*)(op))); | ||||||||||||||||
2557 | return new; | ||||||||||||||||
2558 | } | ||||||||||||||||
2559 | |||||||||||||||||
2560 | /*NUMPY_API*/ | ||||||||||||||||
2561 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
2562 | PyArray_EnsureAnyArray(PyObject *op) | ||||||||||||||||
2563 | { | ||||||||||||||||
2564 | if (op && PyArray_Check(op)((((PyObject*)(op))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(op))->ob_type), (&PyArray_Type)))) { | ||||||||||||||||
2565 | return op; | ||||||||||||||||
2566 | } | ||||||||||||||||
2567 | return PyArray_EnsureArray(op); | ||||||||||||||||
2568 | } | ||||||||||||||||
2569 | |||||||||||||||||
2570 | /* | ||||||||||||||||
2571 | * Private implementation of PyArray_CopyAnyInto with an additional order | ||||||||||||||||
2572 | * parameter. | ||||||||||||||||
2573 | */ | ||||||||||||||||
2574 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||||||||||
2575 | PyArray_CopyAsFlat(PyArrayObject *dst, PyArrayObject *src, NPY_ORDER order) | ||||||||||||||||
2576 | { | ||||||||||||||||
2577 | NpyIter *dst_iter, *src_iter; | ||||||||||||||||
2578 | |||||||||||||||||
2579 | NpyIter_IterNextFunc *dst_iternext, *src_iternext; | ||||||||||||||||
2580 | char **dst_dataptr, **src_dataptr; | ||||||||||||||||
2581 | npy_intp dst_stride, src_stride; | ||||||||||||||||
2582 | npy_intp *dst_countptr, *src_countptr; | ||||||||||||||||
2583 | npy_uint32 baseflags; | ||||||||||||||||
2584 | |||||||||||||||||
2585 | npy_intp dst_count, src_count, count; | ||||||||||||||||
2586 | npy_intp dst_size, src_size; | ||||||||||||||||
2587 | int needs_api; | ||||||||||||||||
2588 | |||||||||||||||||
2589 | NPY_BEGIN_THREADS_DEFPyThreadState *_save=((void*)0);; | ||||||||||||||||
2590 | |||||||||||||||||
2591 | if (PyArray_FailUnlessWriteable(dst, "destination array") < 0) { | ||||||||||||||||
2592 | return -1; | ||||||||||||||||
2593 | } | ||||||||||||||||
2594 | |||||||||||||||||
2595 | /* | ||||||||||||||||
2596 | * If the shapes match and a particular order is forced | ||||||||||||||||
2597 | * for both, use the more efficient CopyInto | ||||||||||||||||
2598 | */ | ||||||||||||||||
2599 | if (order != NPY_ANYORDER && order != NPY_KEEPORDER && | ||||||||||||||||
2600 | PyArray_NDIM(dst) == PyArray_NDIM(src) && | ||||||||||||||||
2601 | PyArray_CompareLists(PyArray_DIMS(dst), PyArray_DIMS(src), | ||||||||||||||||
2602 | PyArray_NDIM(dst))) { | ||||||||||||||||
2603 | return PyArray_CopyInto(dst, src); | ||||||||||||||||
2604 | } | ||||||||||||||||
2605 | |||||||||||||||||
2606 | dst_size = PyArray_SIZE(dst)PyArray_MultiplyList(PyArray_DIMS(dst), PyArray_NDIM(dst)); | ||||||||||||||||
2607 | src_size = PyArray_SIZE(src)PyArray_MultiplyList(PyArray_DIMS(src), PyArray_NDIM(src)); | ||||||||||||||||
2608 | if (dst_size != src_size) { | ||||||||||||||||
2609 | PyErr_Format(PyExc_ValueError, | ||||||||||||||||
2610 | "cannot copy from array of size %" NPY_INTP_FMT"ld" " into an array " | ||||||||||||||||
2611 | "of size %" NPY_INTP_FMT"ld", src_size, dst_size); | ||||||||||||||||
2612 | return -1; | ||||||||||||||||
2613 | } | ||||||||||||||||
2614 | |||||||||||||||||
2615 | /* Zero-sized arrays require nothing be done */ | ||||||||||||||||
2616 | if (dst_size == 0) { | ||||||||||||||||
2617 | return 0; | ||||||||||||||||
2618 | } | ||||||||||||||||
2619 | |||||||||||||||||
2620 | baseflags = NPY_ITER_EXTERNAL_LOOP0x00000008 | | ||||||||||||||||
2621 | NPY_ITER_DONT_NEGATE_STRIDES0x00001000 | | ||||||||||||||||
2622 | NPY_ITER_REFS_OK0x00000020; | ||||||||||||||||
2623 | |||||||||||||||||
2624 | /* | ||||||||||||||||
2625 | * This copy is based on matching C-order traversals of src and dst. | ||||||||||||||||
2626 | * By using two iterators, we can find maximal sub-chunks that | ||||||||||||||||
2627 | * can be processed at once. | ||||||||||||||||
2628 | */ | ||||||||||||||||
2629 | dst_iter = NpyIter_New(dst, NPY_ITER_WRITEONLY0x00040000 | baseflags, | ||||||||||||||||
2630 | order, | ||||||||||||||||
2631 | NPY_NO_CASTING, | ||||||||||||||||
2632 | NULL((void*)0)); | ||||||||||||||||
2633 | if (dst_iter == NULL((void*)0)) { | ||||||||||||||||
2634 | return -1; | ||||||||||||||||
2635 | } | ||||||||||||||||
2636 | src_iter = NpyIter_New(src, NPY_ITER_READONLY0x00020000 | baseflags, | ||||||||||||||||
2637 | order, | ||||||||||||||||
2638 | NPY_NO_CASTING, | ||||||||||||||||
2639 | NULL((void*)0)); | ||||||||||||||||
2640 | if (src_iter == NULL((void*)0)) { | ||||||||||||||||
2641 | NpyIter_Deallocate(dst_iter); | ||||||||||||||||
2642 | return -1; | ||||||||||||||||
2643 | } | ||||||||||||||||
2644 | |||||||||||||||||
2645 | /* Get all the values needed for the inner loop */ | ||||||||||||||||
2646 | dst_iternext = NpyIter_GetIterNext(dst_iter, NULL((void*)0)); | ||||||||||||||||
2647 | dst_dataptr = NpyIter_GetDataPtrArray(dst_iter); | ||||||||||||||||
2648 | /* Since buffering is disabled, we can cache the stride */ | ||||||||||||||||
2649 | dst_stride = NpyIter_GetInnerStrideArray(dst_iter)[0]; | ||||||||||||||||
2650 | dst_countptr = NpyIter_GetInnerLoopSizePtr(dst_iter); | ||||||||||||||||
2651 | |||||||||||||||||
2652 | src_iternext = NpyIter_GetIterNext(src_iter, NULL((void*)0)); | ||||||||||||||||
2653 | src_dataptr = NpyIter_GetDataPtrArray(src_iter); | ||||||||||||||||
2654 | /* Since buffering is disabled, we can cache the stride */ | ||||||||||||||||
2655 | src_stride = NpyIter_GetInnerStrideArray(src_iter)[0]; | ||||||||||||||||
2656 | src_countptr = NpyIter_GetInnerLoopSizePtr(src_iter); | ||||||||||||||||
2657 | |||||||||||||||||
2658 | if (dst_iternext == NULL((void*)0) || src_iternext == NULL((void*)0)) { | ||||||||||||||||
2659 | NpyIter_Deallocate(dst_iter); | ||||||||||||||||
2660 | NpyIter_Deallocate(src_iter); | ||||||||||||||||
2661 | return -1; | ||||||||||||||||
2662 | } | ||||||||||||||||
2663 | |||||||||||||||||
2664 | needs_api = NpyIter_IterationNeedsAPI(dst_iter) || | ||||||||||||||||
2665 | NpyIter_IterationNeedsAPI(src_iter); | ||||||||||||||||
2666 | |||||||||||||||||
2667 | /* | ||||||||||||||||
2668 | * Because buffering is disabled in the iterator, the inner loop | ||||||||||||||||
2669 | * strides will be the same throughout the iteration loop. Thus, | ||||||||||||||||
2670 | * we can pass them to this function to take advantage of | ||||||||||||||||
2671 | * contiguous strides, etc. | ||||||||||||||||
2672 | */ | ||||||||||||||||
2673 | NPY_cast_info cast_info; | ||||||||||||||||
2674 | if (PyArray_GetDTypeTransferFunction( | ||||||||||||||||
2675 | IsUintAligned(src) && IsAligned(src) && | ||||||||||||||||
2676 | IsUintAligned(dst) && IsAligned(dst), | ||||||||||||||||
2677 | src_stride, dst_stride, | ||||||||||||||||
2678 | PyArray_DESCR(src), PyArray_DESCR(dst), | ||||||||||||||||
2679 | 0, | ||||||||||||||||
2680 | &cast_info, &needs_api) != NPY_SUCCEED1) { | ||||||||||||||||
2681 | NpyIter_Deallocate(dst_iter); | ||||||||||||||||
2682 | NpyIter_Deallocate(src_iter); | ||||||||||||||||
2683 | return -1; | ||||||||||||||||
2684 | } | ||||||||||||||||
2685 | |||||||||||||||||
2686 | if (!needs_api) { | ||||||||||||||||
2687 | NPY_BEGIN_THREADSdo {_save = PyEval_SaveThread();} while (0);; | ||||||||||||||||
2688 | } | ||||||||||||||||
2689 | |||||||||||||||||
2690 | dst_count = *dst_countptr; | ||||||||||||||||
2691 | src_count = *src_countptr; | ||||||||||||||||
2692 | char *args[2] = {src_dataptr[0], dst_dataptr[0]}; | ||||||||||||||||
2693 | npy_intp strides[2] = {src_stride, dst_stride}; | ||||||||||||||||
2694 | |||||||||||||||||
2695 | int res = 0; | ||||||||||||||||
2696 | for(;;) { | ||||||||||||||||
2697 | /* Transfer the biggest amount that fits both */ | ||||||||||||||||
2698 | count = (src_count < dst_count) ? src_count : dst_count; | ||||||||||||||||
2699 | if (cast_info.func(&cast_info.context, | ||||||||||||||||
2700 | args, &count, strides, cast_info.auxdata) < 0) { | ||||||||||||||||
2701 | res = -1; | ||||||||||||||||
2702 | break; | ||||||||||||||||
2703 | } | ||||||||||||||||
2704 | |||||||||||||||||
2705 | /* If we exhausted the dst block, refresh it */ | ||||||||||||||||
2706 | if (dst_count == count) { | ||||||||||||||||
2707 | res = dst_iternext(dst_iter); | ||||||||||||||||
2708 | if (!res) { | ||||||||||||||||
2709 | break; | ||||||||||||||||
2710 | } | ||||||||||||||||
2711 | dst_count = *dst_countptr; | ||||||||||||||||
2712 | args[1] = dst_dataptr[0]; | ||||||||||||||||
2713 | } | ||||||||||||||||
2714 | else { | ||||||||||||||||
2715 | dst_count -= count; | ||||||||||||||||
2716 | args[1] += count*dst_stride; | ||||||||||||||||
2717 | } | ||||||||||||||||
2718 | |||||||||||||||||
2719 | /* If we exhausted the src block, refresh it */ | ||||||||||||||||
2720 | if (src_count == count) { | ||||||||||||||||
2721 | res = src_iternext(src_iter); | ||||||||||||||||
2722 | if (!res) { | ||||||||||||||||
2723 | break; | ||||||||||||||||
2724 | } | ||||||||||||||||
2725 | src_count = *src_countptr; | ||||||||||||||||
2726 | args[0] = src_dataptr[0]; | ||||||||||||||||
2727 | } | ||||||||||||||||
2728 | else { | ||||||||||||||||
2729 | src_count -= count; | ||||||||||||||||
2730 | args[0] += count*src_stride; | ||||||||||||||||
2731 | } | ||||||||||||||||
2732 | } | ||||||||||||||||
2733 | |||||||||||||||||
2734 | NPY_END_THREADSdo { if (_save) { PyEval_RestoreThread(_save); _save = ((void *)0);} } while (0);; | ||||||||||||||||
2735 | |||||||||||||||||
2736 | NPY_cast_info_xfree(&cast_info); | ||||||||||||||||
2737 | NpyIter_Deallocate(dst_iter); | ||||||||||||||||
2738 | NpyIter_Deallocate(src_iter); | ||||||||||||||||
2739 | if (res > 0) { | ||||||||||||||||
2740 | /* The iteration stopped successfully, do not report an error */ | ||||||||||||||||
2741 | return 0; | ||||||||||||||||
2742 | } | ||||||||||||||||
2743 | return res; | ||||||||||||||||
2744 | } | ||||||||||||||||
2745 | |||||||||||||||||
2746 | /*NUMPY_API | ||||||||||||||||
2747 | * Copy an Array into another array -- memory must not overlap | ||||||||||||||||
2748 | * Does not require src and dest to have "broadcastable" shapes | ||||||||||||||||
2749 | * (only the same number of elements). | ||||||||||||||||
2750 | * | ||||||||||||||||
2751 | * TODO: For NumPy 2.0, this could accept an order parameter which | ||||||||||||||||
2752 | * only allows NPY_CORDER and NPY_FORDER. Could also rename | ||||||||||||||||
2753 | * this to CopyAsFlat to make the name more intuitive. | ||||||||||||||||
2754 | * | ||||||||||||||||
2755 | * Returns 0 on success, -1 on error. | ||||||||||||||||
2756 | */ | ||||||||||||||||
2757 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||||||||||
2758 | PyArray_CopyAnyInto(PyArrayObject *dst, PyArrayObject *src) | ||||||||||||||||
2759 | { | ||||||||||||||||
2760 | return PyArray_CopyAsFlat(dst, src, NPY_CORDER); | ||||||||||||||||
2761 | } | ||||||||||||||||
2762 | |||||||||||||||||
2763 | /*NUMPY_API | ||||||||||||||||
2764 | * Copy an Array into another array. | ||||||||||||||||
2765 | * Broadcast to the destination shape if necessary. | ||||||||||||||||
2766 | * | ||||||||||||||||
2767 | * Returns 0 on success, -1 on failure. | ||||||||||||||||
2768 | */ | ||||||||||||||||
2769 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||||||||||
2770 | PyArray_CopyInto(PyArrayObject *dst, PyArrayObject *src) | ||||||||||||||||
2771 | { | ||||||||||||||||
2772 | return PyArray_AssignArray(dst, src, NULL((void*)0), NPY_UNSAFE_CASTING); | ||||||||||||||||
2773 | } | ||||||||||||||||
2774 | |||||||||||||||||
2775 | /*NUMPY_API | ||||||||||||||||
2776 | * Move the memory of one array into another, allowing for overlapping data. | ||||||||||||||||
2777 | * | ||||||||||||||||
2778 | * Returns 0 on success, negative on failure. | ||||||||||||||||
2779 | */ | ||||||||||||||||
2780 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | ||||||||||||||||
2781 | PyArray_MoveInto(PyArrayObject *dst, PyArrayObject *src) | ||||||||||||||||
2782 | { | ||||||||||||||||
2783 | return PyArray_AssignArray(dst, src, NULL((void*)0), NPY_UNSAFE_CASTING); | ||||||||||||||||
2784 | } | ||||||||||||||||
2785 | |||||||||||||||||
2786 | /*NUMPY_API | ||||||||||||||||
2787 | * PyArray_CheckAxis | ||||||||||||||||
2788 | * | ||||||||||||||||
2789 | * check that axis is valid | ||||||||||||||||
2790 | * convert 0-d arrays to 1-d arrays | ||||||||||||||||
2791 | */ | ||||||||||||||||
2792 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
2793 | PyArray_CheckAxis(PyArrayObject *arr, int *axis, int flags) | ||||||||||||||||
2794 | { | ||||||||||||||||
2795 | PyObject *temp1, *temp2; | ||||||||||||||||
2796 | int n = PyArray_NDIM(arr); | ||||||||||||||||
2797 | |||||||||||||||||
2798 | if (*axis == NPY_MAXDIMS32 || n == 0) { | ||||||||||||||||
2799 | if (n != 1) { | ||||||||||||||||
2800 | temp1 = PyArray_Ravel(arr,0); | ||||||||||||||||
2801 | if (temp1 == NULL((void*)0)) { | ||||||||||||||||
2802 | *axis = 0; | ||||||||||||||||
2803 | return NULL((void*)0); | ||||||||||||||||
2804 | } | ||||||||||||||||
2805 | if (*axis == NPY_MAXDIMS32) { | ||||||||||||||||
2806 | *axis = PyArray_NDIM((PyArrayObject *)temp1)-1; | ||||||||||||||||
2807 | } | ||||||||||||||||
2808 | } | ||||||||||||||||
2809 | else { | ||||||||||||||||
2810 | temp1 = (PyObject *)arr; | ||||||||||||||||
2811 | Py_INCREF(temp1)_Py_INCREF(((PyObject*)(temp1))); | ||||||||||||||||
2812 | *axis = 0; | ||||||||||||||||
2813 | } | ||||||||||||||||
2814 | if (!flags && *axis == 0) { | ||||||||||||||||
2815 | return temp1; | ||||||||||||||||
2816 | } | ||||||||||||||||
2817 | } | ||||||||||||||||
2818 | else { | ||||||||||||||||
2819 | temp1 = (PyObject *)arr; | ||||||||||||||||
2820 | Py_INCREF(temp1)_Py_INCREF(((PyObject*)(temp1))); | ||||||||||||||||
2821 | } | ||||||||||||||||
2822 | if (flags) { | ||||||||||||||||
2823 | temp2 = PyArray_CheckFromAny((PyObject *)temp1, NULL((void*)0), | ||||||||||||||||
2824 | 0, 0, flags, NULL((void*)0)); | ||||||||||||||||
2825 | Py_DECREF(temp1)_Py_DECREF(((PyObject*)(temp1))); | ||||||||||||||||
2826 | if (temp2 == NULL((void*)0)) { | ||||||||||||||||
2827 | return NULL((void*)0); | ||||||||||||||||
2828 | } | ||||||||||||||||
2829 | } | ||||||||||||||||
2830 | else { | ||||||||||||||||
2831 | temp2 = (PyObject *)temp1; | ||||||||||||||||
2832 | } | ||||||||||||||||
2833 | n = PyArray_NDIM((PyArrayObject *)temp2); | ||||||||||||||||
2834 | if (check_and_adjust_axis(axis, n) < 0) { | ||||||||||||||||
2835 | Py_DECREF(temp2)_Py_DECREF(((PyObject*)(temp2))); | ||||||||||||||||
2836 | return NULL((void*)0); | ||||||||||||||||
2837 | } | ||||||||||||||||
2838 | return temp2; | ||||||||||||||||
2839 | } | ||||||||||||||||
2840 | |||||||||||||||||
2841 | /*NUMPY_API | ||||||||||||||||
2842 | * Zeros | ||||||||||||||||
2843 | * | ||||||||||||||||
2844 | * steals a reference to type. On failure or when dtype->subarray is | ||||||||||||||||
2845 | * true, dtype will be decrefed. | ||||||||||||||||
2846 | * accepts NULL type | ||||||||||||||||
2847 | */ | ||||||||||||||||
2848 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
2849 | PyArray_Zeros(int nd, npy_intp const *dims, PyArray_Descr *type, int is_f_order) | ||||||||||||||||
2850 | { | ||||||||||||||||
2851 | PyArrayObject *ret; | ||||||||||||||||
2852 | |||||||||||||||||
2853 | if (!type) { | ||||||||||||||||
2854 | type = PyArray_DescrFromType(NPY_DEFAULT_TYPENPY_DOUBLE); | ||||||||||||||||
2855 | } | ||||||||||||||||
2856 | |||||||||||||||||
2857 | ret = (PyArrayObject *)PyArray_NewFromDescr_int( | ||||||||||||||||
2858 | &PyArray_Type, type, | ||||||||||||||||
2859 | nd, dims, NULL((void*)0), NULL((void*)0), | ||||||||||||||||
2860 | is_f_order, NULL((void*)0), NULL((void*)0), | ||||||||||||||||
2861 | 1, 0); | ||||||||||||||||
2862 | |||||||||||||||||
2863 | if (ret == NULL((void*)0)) { | ||||||||||||||||
2864 | return NULL((void*)0); | ||||||||||||||||
2865 | } | ||||||||||||||||
2866 | |||||||||||||||||
2867 | /* handle objects */ | ||||||||||||||||
2868 | if (PyDataType_REFCHK(PyArray_DESCR(ret))(((PyArray_DESCR(ret))->flags & (0x01)) == (0x01))) { | ||||||||||||||||
2869 | if (_zerofill(ret) < 0) { | ||||||||||||||||
2870 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
2871 | return NULL((void*)0); | ||||||||||||||||
2872 | } | ||||||||||||||||
2873 | } | ||||||||||||||||
2874 | |||||||||||||||||
2875 | |||||||||||||||||
2876 | return (PyObject *)ret; | ||||||||||||||||
2877 | |||||||||||||||||
2878 | } | ||||||||||||||||
2879 | |||||||||||||||||
2880 | /*NUMPY_API | ||||||||||||||||
2881 | * Empty | ||||||||||||||||
2882 | * | ||||||||||||||||
2883 | * accepts NULL type | ||||||||||||||||
2884 | * steals a reference to type | ||||||||||||||||
2885 | */ | ||||||||||||||||
2886 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
2887 | PyArray_Empty(int nd, npy_intp const *dims, PyArray_Descr *type, int is_f_order) | ||||||||||||||||
2888 | { | ||||||||||||||||
2889 | PyArrayObject *ret; | ||||||||||||||||
2890 | |||||||||||||||||
2891 | if (!type) type = PyArray_DescrFromType(NPY_DEFAULT_TYPENPY_DOUBLE); | ||||||||||||||||
2892 | |||||||||||||||||
2893 | /* | ||||||||||||||||
2894 | * PyArray_NewFromDescr steals a ref, | ||||||||||||||||
2895 | * but we need to look at type later. | ||||||||||||||||
2896 | * */ | ||||||||||||||||
2897 | Py_INCREF(type)_Py_INCREF(((PyObject*)(type))); | ||||||||||||||||
2898 | |||||||||||||||||
2899 | ret = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, | ||||||||||||||||
2900 | type, nd, dims, | ||||||||||||||||
2901 | NULL((void*)0), NULL((void*)0), | ||||||||||||||||
2902 | is_f_order, NULL((void*)0)); | ||||||||||||||||
2903 | if (ret != NULL((void*)0) && PyDataType_REFCHK(type)(((type)->flags & (0x01)) == (0x01))) { | ||||||||||||||||
2904 | PyArray_FillObjectArray(ret, Py_None(&_Py_NoneStruct)); | ||||||||||||||||
2905 | if (PyErr_Occurred()) { | ||||||||||||||||
2906 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
2907 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | ||||||||||||||||
2908 | return NULL((void*)0); | ||||||||||||||||
2909 | } | ||||||||||||||||
2910 | } | ||||||||||||||||
2911 | |||||||||||||||||
2912 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | ||||||||||||||||
2913 | return (PyObject *)ret; | ||||||||||||||||
2914 | } | ||||||||||||||||
2915 | |||||||||||||||||
2916 | /* | ||||||||||||||||
2917 | * Like ceil(value), but check for overflow. | ||||||||||||||||
2918 | * | ||||||||||||||||
2919 | * Return 0 on success, -1 on failure. In case of failure, set a PyExc_Overflow | ||||||||||||||||
2920 | * exception | ||||||||||||||||
2921 | */ | ||||||||||||||||
2922 | static npy_intp | ||||||||||||||||
2923 | _arange_safe_ceil_to_intp(double value) | ||||||||||||||||
2924 | { | ||||||||||||||||
2925 | double ivalue; | ||||||||||||||||
2926 | |||||||||||||||||
2927 | ivalue = npy_ceil(value); | ||||||||||||||||
2928 | /* condition inverted to handle NaN */ | ||||||||||||||||
2929 | if (npy_isnan(ivalue)) { | ||||||||||||||||
2930 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
2931 | "arange: cannot compute length"); | ||||||||||||||||
2932 | return -1; | ||||||||||||||||
2933 | } | ||||||||||||||||
2934 | if (!((double)NPY_MIN_INTP(-9223372036854775807L -1L) <= ivalue && ivalue <= (double)NPY_MAX_INTP9223372036854775807L)) { | ||||||||||||||||
2935 | PyErr_SetString(PyExc_OverflowError, | ||||||||||||||||
2936 | "arange: overflow while computing length"); | ||||||||||||||||
2937 | return -1; | ||||||||||||||||
2938 | } | ||||||||||||||||
2939 | |||||||||||||||||
2940 | return (npy_intp)ivalue; | ||||||||||||||||
2941 | } | ||||||||||||||||
2942 | |||||||||||||||||
2943 | |||||||||||||||||
2944 | /*NUMPY_API | ||||||||||||||||
2945 | Arange, | ||||||||||||||||
2946 | */ | ||||||||||||||||
2947 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
2948 | PyArray_Arange(double start, double stop, double step, int type_num) | ||||||||||||||||
2949 | { | ||||||||||||||||
2950 | npy_intp length; | ||||||||||||||||
2951 | PyArrayObject *range; | ||||||||||||||||
2952 | PyArray_ArrFuncs *funcs; | ||||||||||||||||
2953 | PyObject *obj; | ||||||||||||||||
2954 | int ret; | ||||||||||||||||
2955 | double delta, tmp_len; | ||||||||||||||||
2956 | NPY_BEGIN_THREADS_DEFPyThreadState *_save=((void*)0);; | ||||||||||||||||
2957 | |||||||||||||||||
2958 | delta = stop - start; | ||||||||||||||||
2959 | tmp_len = delta/step; | ||||||||||||||||
2960 | |||||||||||||||||
2961 | /* Underflow and divide-by-inf check */ | ||||||||||||||||
2962 | if (tmp_len == 0.0 && delta != 0.0) { | ||||||||||||||||
2963 | if (npy_signbit(tmp_len)) { | ||||||||||||||||
2964 | length = 0; | ||||||||||||||||
2965 | } | ||||||||||||||||
2966 | else { | ||||||||||||||||
2967 | length = 1; | ||||||||||||||||
2968 | } | ||||||||||||||||
2969 | } | ||||||||||||||||
2970 | else { | ||||||||||||||||
2971 | length = _arange_safe_ceil_to_intp(tmp_len); | ||||||||||||||||
2972 | if (error_converting(length)(((length) == -1) && PyErr_Occurred())) { | ||||||||||||||||
2973 | return NULL((void*)0); | ||||||||||||||||
2974 | } | ||||||||||||||||
2975 | } | ||||||||||||||||
2976 | |||||||||||||||||
2977 | if (length <= 0) { | ||||||||||||||||
2978 | length = 0; | ||||||||||||||||
2979 | return PyArray_New(&PyArray_Type, 1, &length, type_num, | ||||||||||||||||
2980 | NULL((void*)0), NULL((void*)0), 0, 0, NULL((void*)0)); | ||||||||||||||||
2981 | } | ||||||||||||||||
2982 | range = (PyArrayObject *)PyArray_New(&PyArray_Type, 1, &length, type_num, | ||||||||||||||||
2983 | NULL((void*)0), NULL((void*)0), 0, 0, NULL((void*)0)); | ||||||||||||||||
2984 | if (range == NULL((void*)0)) { | ||||||||||||||||
2985 | return NULL((void*)0); | ||||||||||||||||
2986 | } | ||||||||||||||||
2987 | funcs = PyArray_DESCR(range)->f; | ||||||||||||||||
2988 | |||||||||||||||||
2989 | /* | ||||||||||||||||
2990 | * place start in the buffer and the next value in the second position | ||||||||||||||||
2991 | * if length > 2, then call the inner loop, otherwise stop | ||||||||||||||||
2992 | */ | ||||||||||||||||
2993 | obj = PyFloat_FromDouble(start); | ||||||||||||||||
2994 | ret = funcs->setitem(obj, PyArray_DATA(range), range); | ||||||||||||||||
2995 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | ||||||||||||||||
2996 | if (ret < 0) { | ||||||||||||||||
2997 | goto fail; | ||||||||||||||||
2998 | } | ||||||||||||||||
2999 | if (length == 1) { | ||||||||||||||||
3000 | return (PyObject *)range; | ||||||||||||||||
3001 | } | ||||||||||||||||
3002 | obj = PyFloat_FromDouble(start + step); | ||||||||||||||||
3003 | ret = funcs->setitem(obj, PyArray_BYTES(range)+PyArray_ITEMSIZE(range), | ||||||||||||||||
3004 | range); | ||||||||||||||||
3005 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | ||||||||||||||||
3006 | if (ret < 0) { | ||||||||||||||||
3007 | goto fail; | ||||||||||||||||
3008 | } | ||||||||||||||||
3009 | if (length == 2) { | ||||||||||||||||
3010 | return (PyObject *)range; | ||||||||||||||||
3011 | } | ||||||||||||||||
3012 | if (!funcs->fill) { | ||||||||||||||||
3013 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3014 | "no fill-function for data-type."); | ||||||||||||||||
3015 | Py_DECREF(range)_Py_DECREF(((PyObject*)(range))); | ||||||||||||||||
3016 | return NULL((void*)0); | ||||||||||||||||
3017 | } | ||||||||||||||||
3018 | NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(range))do {if (!(((((PyArray_DESCR(range)))->flags & (0x10)) == (0x10)))) do {_save = PyEval_SaveThread();} while (0);;} while (0);; | ||||||||||||||||
3019 | funcs->fill(PyArray_DATA(range), length, range); | ||||||||||||||||
3020 | NPY_END_THREADSdo { if (_save) { PyEval_RestoreThread(_save); _save = ((void *)0);} } while (0);; | ||||||||||||||||
3021 | if (PyErr_Occurred()) { | ||||||||||||||||
3022 | goto fail; | ||||||||||||||||
3023 | } | ||||||||||||||||
3024 | return (PyObject *)range; | ||||||||||||||||
3025 | |||||||||||||||||
3026 | fail: | ||||||||||||||||
3027 | Py_DECREF(range)_Py_DECREF(((PyObject*)(range))); | ||||||||||||||||
3028 | return NULL((void*)0); | ||||||||||||||||
3029 | } | ||||||||||||||||
3030 | |||||||||||||||||
3031 | /* | ||||||||||||||||
3032 | * the formula is len = (intp) ceil((stop - start) / step); | ||||||||||||||||
3033 | */ | ||||||||||||||||
3034 | static npy_intp | ||||||||||||||||
3035 | _calc_length(PyObject *start, PyObject *stop, PyObject *step, PyObject **next, int cmplx) | ||||||||||||||||
3036 | { | ||||||||||||||||
3037 | npy_intp len, tmp; | ||||||||||||||||
3038 | PyObject *zero, *val; | ||||||||||||||||
3039 | int next_is_nonzero, val_is_zero; | ||||||||||||||||
3040 | double value; | ||||||||||||||||
3041 | |||||||||||||||||
3042 | *next = PyNumber_Subtract(stop, start); | ||||||||||||||||
3043 | if (!(*next)) { | ||||||||||||||||
3044 | if (PyTuple_Check(stop)((((((PyObject*)(stop))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | ||||||||||||||||
3045 | PyErr_Clear(); | ||||||||||||||||
3046 | PyErr_SetString(PyExc_TypeError, | ||||||||||||||||
3047 | "arange: scalar arguments expected "\ | ||||||||||||||||
3048 | "instead of a tuple."); | ||||||||||||||||
3049 | } | ||||||||||||||||
3050 | return -1; | ||||||||||||||||
3051 | } | ||||||||||||||||
3052 | |||||||||||||||||
3053 | zero = PyLong_FromLong(0); | ||||||||||||||||
3054 | if (!zero) { | ||||||||||||||||
3055 | Py_DECREF(*next)_Py_DECREF(((PyObject*)(*next))); | ||||||||||||||||
3056 | *next = NULL((void*)0); | ||||||||||||||||
3057 | return -1; | ||||||||||||||||
3058 | } | ||||||||||||||||
3059 | |||||||||||||||||
3060 | next_is_nonzero = PyObject_RichCompareBool(*next, zero, Py_NE3); | ||||||||||||||||
3061 | if (next_is_nonzero == -1) { | ||||||||||||||||
3062 | Py_DECREF(zero)_Py_DECREF(((PyObject*)(zero))); | ||||||||||||||||
3063 | Py_DECREF(*next)_Py_DECREF(((PyObject*)(*next))); | ||||||||||||||||
3064 | *next = NULL((void*)0); | ||||||||||||||||
3065 | return -1; | ||||||||||||||||
3066 | } | ||||||||||||||||
3067 | val = PyNumber_TrueDivide(*next, step); | ||||||||||||||||
3068 | Py_DECREF(*next)_Py_DECREF(((PyObject*)(*next))); | ||||||||||||||||
3069 | *next = NULL((void*)0); | ||||||||||||||||
3070 | |||||||||||||||||
3071 | if (!val) { | ||||||||||||||||
3072 | Py_DECREF(zero)_Py_DECREF(((PyObject*)(zero))); | ||||||||||||||||
3073 | return -1; | ||||||||||||||||
3074 | } | ||||||||||||||||
3075 | |||||||||||||||||
3076 | val_is_zero = PyObject_RichCompareBool(val, zero, Py_EQ2); | ||||||||||||||||
3077 | Py_DECREF(zero)_Py_DECREF(((PyObject*)(zero))); | ||||||||||||||||
3078 | if (val_is_zero == -1) { | ||||||||||||||||
3079 | Py_DECREF(val)_Py_DECREF(((PyObject*)(val))); | ||||||||||||||||
3080 | return -1; | ||||||||||||||||
3081 | } | ||||||||||||||||
3082 | |||||||||||||||||
3083 | if (cmplx && PyComplex_Check(val)((((PyObject*)(val))->ob_type) == (&PyComplex_Type) || PyType_IsSubtype((((PyObject*)(val))->ob_type), (&PyComplex_Type )))) { | ||||||||||||||||
3084 | value = PyComplex_RealAsDouble(val); | ||||||||||||||||
3085 | if (error_converting(value)(((value) == -1) && PyErr_Occurred())) { | ||||||||||||||||
3086 | Py_DECREF(val)_Py_DECREF(((PyObject*)(val))); | ||||||||||||||||
3087 | return -1; | ||||||||||||||||
3088 | } | ||||||||||||||||
3089 | len = _arange_safe_ceil_to_intp(value); | ||||||||||||||||
3090 | if (error_converting(len)(((len) == -1) && PyErr_Occurred())) { | ||||||||||||||||
3091 | Py_DECREF(val)_Py_DECREF(((PyObject*)(val))); | ||||||||||||||||
3092 | return -1; | ||||||||||||||||
3093 | } | ||||||||||||||||
3094 | value = PyComplex_ImagAsDouble(val); | ||||||||||||||||
3095 | Py_DECREF(val)_Py_DECREF(((PyObject*)(val))); | ||||||||||||||||
3096 | if (error_converting(value)(((value) == -1) && PyErr_Occurred())) { | ||||||||||||||||
3097 | return -1; | ||||||||||||||||
3098 | } | ||||||||||||||||
3099 | tmp = _arange_safe_ceil_to_intp(value); | ||||||||||||||||
3100 | if (error_converting(tmp)(((tmp) == -1) && PyErr_Occurred())) { | ||||||||||||||||
3101 | return -1; | ||||||||||||||||
3102 | } | ||||||||||||||||
3103 | len = PyArray_MIN(len, tmp)(((len)<(tmp))?(len):(tmp)); | ||||||||||||||||
3104 | } | ||||||||||||||||
3105 | else { | ||||||||||||||||
3106 | value = PyFloat_AsDouble(val); | ||||||||||||||||
3107 | Py_DECREF(val)_Py_DECREF(((PyObject*)(val))); | ||||||||||||||||
3108 | if (error_converting(value)(((value) == -1) && PyErr_Occurred())) { | ||||||||||||||||
3109 | return -1; | ||||||||||||||||
3110 | } | ||||||||||||||||
3111 | |||||||||||||||||
3112 | /* Underflow and divide-by-inf check */ | ||||||||||||||||
3113 | if (val_is_zero && next_is_nonzero) { | ||||||||||||||||
3114 | if (npy_signbit(value)) { | ||||||||||||||||
3115 | len = 0; | ||||||||||||||||
3116 | } | ||||||||||||||||
3117 | else { | ||||||||||||||||
3118 | len = 1; | ||||||||||||||||
3119 | } | ||||||||||||||||
3120 | } | ||||||||||||||||
3121 | else { | ||||||||||||||||
3122 | len = _arange_safe_ceil_to_intp(value); | ||||||||||||||||
3123 | if (error_converting(len)(((len) == -1) && PyErr_Occurred())) { | ||||||||||||||||
3124 | return -1; | ||||||||||||||||
3125 | } | ||||||||||||||||
3126 | } | ||||||||||||||||
3127 | } | ||||||||||||||||
3128 | |||||||||||||||||
3129 | if (len > 0) { | ||||||||||||||||
3130 | *next = PyNumber_Add(start, step); | ||||||||||||||||
3131 | if (!*next) { | ||||||||||||||||
3132 | return -1; | ||||||||||||||||
3133 | } | ||||||||||||||||
3134 | } | ||||||||||||||||
3135 | return len; | ||||||||||||||||
3136 | } | ||||||||||||||||
3137 | |||||||||||||||||
3138 | /*NUMPY_API | ||||||||||||||||
3139 | * | ||||||||||||||||
3140 | * ArangeObj, | ||||||||||||||||
3141 | * | ||||||||||||||||
3142 | * this doesn't change the references | ||||||||||||||||
3143 | */ | ||||||||||||||||
3144 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
3145 | PyArray_ArangeObj(PyObject *start, PyObject *stop, PyObject *step, PyArray_Descr *dtype) | ||||||||||||||||
3146 | { | ||||||||||||||||
3147 | PyArrayObject *range; | ||||||||||||||||
3148 | PyArray_ArrFuncs *funcs; | ||||||||||||||||
3149 | PyObject *next, *err; | ||||||||||||||||
3150 | npy_intp length; | ||||||||||||||||
3151 | PyArray_Descr *native = NULL((void*)0); | ||||||||||||||||
3152 | int swap; | ||||||||||||||||
3153 | NPY_BEGIN_THREADS_DEFPyThreadState *_save=((void*)0);; | ||||||||||||||||
3154 | |||||||||||||||||
3155 | /* Datetime arange is handled specially */ | ||||||||||||||||
3156 | if ((dtype != NULL((void*)0) && (dtype->type_num == NPY_DATETIME || | ||||||||||||||||
3157 | dtype->type_num == NPY_TIMEDELTA)) || | ||||||||||||||||
3158 | (dtype == NULL((void*)0) && (is_any_numpy_datetime_or_timedelta(start) || | ||||||||||||||||
3159 | is_any_numpy_datetime_or_timedelta(stop) || | ||||||||||||||||
3160 | is_any_numpy_datetime_or_timedelta(step)))) { | ||||||||||||||||
3161 | return (PyObject *)datetime_arange(start, stop, step, dtype); | ||||||||||||||||
3162 | } | ||||||||||||||||
3163 | |||||||||||||||||
3164 | if (!dtype) { | ||||||||||||||||
3165 | PyArray_Descr *deftype; | ||||||||||||||||
3166 | PyArray_Descr *newtype; | ||||||||||||||||
3167 | |||||||||||||||||
3168 | /* intentionally made to be at least NPY_LONG */ | ||||||||||||||||
3169 | deftype = PyArray_DescrFromType(NPY_LONG); | ||||||||||||||||
3170 | newtype = PyArray_DescrFromObject(start, deftype); | ||||||||||||||||
3171 | Py_DECREF(deftype)_Py_DECREF(((PyObject*)(deftype))); | ||||||||||||||||
3172 | if (newtype == NULL((void*)0)) { | ||||||||||||||||
3173 | return NULL((void*)0); | ||||||||||||||||
3174 | } | ||||||||||||||||
3175 | deftype = newtype; | ||||||||||||||||
3176 | if (stop && stop != Py_None(&_Py_NoneStruct)) { | ||||||||||||||||
3177 | newtype = PyArray_DescrFromObject(stop, deftype); | ||||||||||||||||
3178 | Py_DECREF(deftype)_Py_DECREF(((PyObject*)(deftype))); | ||||||||||||||||
3179 | if (newtype == NULL((void*)0)) { | ||||||||||||||||
3180 | return NULL((void*)0); | ||||||||||||||||
3181 | } | ||||||||||||||||
3182 | deftype = newtype; | ||||||||||||||||
3183 | } | ||||||||||||||||
3184 | if (step && step != Py_None(&_Py_NoneStruct)) { | ||||||||||||||||
3185 | newtype = PyArray_DescrFromObject(step, deftype); | ||||||||||||||||
3186 | Py_DECREF(deftype)_Py_DECREF(((PyObject*)(deftype))); | ||||||||||||||||
3187 | if (newtype == NULL((void*)0)) { | ||||||||||||||||
3188 | return NULL((void*)0); | ||||||||||||||||
3189 | } | ||||||||||||||||
3190 | deftype = newtype; | ||||||||||||||||
3191 | } | ||||||||||||||||
3192 | dtype = deftype; | ||||||||||||||||
3193 | } | ||||||||||||||||
3194 | else { | ||||||||||||||||
3195 | Py_INCREF(dtype)_Py_INCREF(((PyObject*)(dtype))); | ||||||||||||||||
3196 | } | ||||||||||||||||
3197 | if (!step || step == Py_None(&_Py_NoneStruct)) { | ||||||||||||||||
3198 | step = PyLong_FromLong(1); | ||||||||||||||||
3199 | } | ||||||||||||||||
3200 | else { | ||||||||||||||||
3201 | Py_XINCREF(step)_Py_XINCREF(((PyObject*)(step))); | ||||||||||||||||
3202 | } | ||||||||||||||||
3203 | if (!stop || stop == Py_None(&_Py_NoneStruct)) { | ||||||||||||||||
3204 | stop = start; | ||||||||||||||||
3205 | start = PyLong_FromLong(0); | ||||||||||||||||
3206 | } | ||||||||||||||||
3207 | else { | ||||||||||||||||
3208 | Py_INCREF(start)_Py_INCREF(((PyObject*)(start))); | ||||||||||||||||
3209 | } | ||||||||||||||||
3210 | /* calculate the length and next = start + step*/ | ||||||||||||||||
3211 | length = _calc_length(start, stop, step, &next, | ||||||||||||||||
3212 | PyTypeNum_ISCOMPLEX(dtype->type_num)(((dtype->type_num) >= NPY_CFLOAT) && ((dtype-> type_num) <= NPY_CLONGDOUBLE))); | ||||||||||||||||
3213 | err = PyErr_Occurred(); | ||||||||||||||||
3214 | if (err) { | ||||||||||||||||
3215 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3216 | if (err && PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) { | ||||||||||||||||
3217 | PyErr_SetString(PyExc_ValueError, "Maximum allowed size exceeded"); | ||||||||||||||||
3218 | } | ||||||||||||||||
3219 | goto fail; | ||||||||||||||||
3220 | } | ||||||||||||||||
3221 | if (length <= 0) { | ||||||||||||||||
3222 | length = 0; | ||||||||||||||||
3223 | range = (PyArrayObject *)PyArray_SimpleNewFromDescr(1, &length, dtype)PyArray_NewFromDescr(&PyArray_Type, dtype, 1, &length , ((void*)0), ((void*)0), 0, ((void*)0)); | ||||||||||||||||
3224 | Py_DECREF(step)_Py_DECREF(((PyObject*)(step))); | ||||||||||||||||
3225 | Py_DECREF(start)_Py_DECREF(((PyObject*)(start))); | ||||||||||||||||
3226 | return (PyObject *)range; | ||||||||||||||||
3227 | } | ||||||||||||||||
3228 | |||||||||||||||||
3229 | /* | ||||||||||||||||
3230 | * If dtype is not in native byte-order then get native-byte | ||||||||||||||||
3231 | * order version. And then swap on the way out. | ||||||||||||||||
3232 | */ | ||||||||||||||||
3233 | if (!PyArray_ISNBO(dtype->byteorder)((dtype->byteorder) != '>')) { | ||||||||||||||||
3234 | native = PyArray_DescrNewByteorder(dtype, NPY_NATBYTE'<'); | ||||||||||||||||
3235 | swap = 1; | ||||||||||||||||
3236 | } | ||||||||||||||||
3237 | else { | ||||||||||||||||
3238 | native = dtype; | ||||||||||||||||
3239 | swap = 0; | ||||||||||||||||
3240 | } | ||||||||||||||||
3241 | |||||||||||||||||
3242 | range = (PyArrayObject *)PyArray_SimpleNewFromDescr(1, &length, native)PyArray_NewFromDescr(&PyArray_Type, native, 1, &length , ((void*)0), ((void*)0), 0, ((void*)0)); | ||||||||||||||||
3243 | if (range == NULL((void*)0)) { | ||||||||||||||||
3244 | goto fail; | ||||||||||||||||
3245 | } | ||||||||||||||||
3246 | |||||||||||||||||
3247 | /* | ||||||||||||||||
3248 | * place start in the buffer and the next value in the second position | ||||||||||||||||
3249 | * if length > 2, then call the inner loop, otherwise stop | ||||||||||||||||
3250 | */ | ||||||||||||||||
3251 | funcs = PyArray_DESCR(range)->f; | ||||||||||||||||
3252 | if (funcs->setitem(start, PyArray_DATA(range), range) < 0) { | ||||||||||||||||
3253 | goto fail; | ||||||||||||||||
3254 | } | ||||||||||||||||
3255 | if (length == 1) { | ||||||||||||||||
3256 | goto finish; | ||||||||||||||||
3257 | } | ||||||||||||||||
3258 | if (funcs->setitem(next, PyArray_BYTES(range)+PyArray_ITEMSIZE(range), | ||||||||||||||||
3259 | range) < 0) { | ||||||||||||||||
3260 | goto fail; | ||||||||||||||||
3261 | } | ||||||||||||||||
3262 | if (length == 2) { | ||||||||||||||||
3263 | goto finish; | ||||||||||||||||
3264 | } | ||||||||||||||||
3265 | if (!funcs->fill) { | ||||||||||||||||
3266 | PyErr_SetString(PyExc_ValueError, "no fill-function for data-type."); | ||||||||||||||||
3267 | Py_DECREF(range)_Py_DECREF(((PyObject*)(range))); | ||||||||||||||||
3268 | goto fail; | ||||||||||||||||
3269 | } | ||||||||||||||||
3270 | NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(range))do {if (!(((((PyArray_DESCR(range)))->flags & (0x10)) == (0x10)))) do {_save = PyEval_SaveThread();} while (0);;} while (0);; | ||||||||||||||||
3271 | funcs->fill(PyArray_DATA(range), length, range); | ||||||||||||||||
3272 | NPY_END_THREADSdo { if (_save) { PyEval_RestoreThread(_save); _save = ((void *)0);} } while (0);; | ||||||||||||||||
3273 | if (PyErr_Occurred()) { | ||||||||||||||||
3274 | goto fail; | ||||||||||||||||
3275 | } | ||||||||||||||||
3276 | finish: | ||||||||||||||||
3277 | /* TODO: This swapping could be handled on the fly by the nditer */ | ||||||||||||||||
3278 | if (swap) { | ||||||||||||||||
3279 | PyObject *new; | ||||||||||||||||
3280 | new = PyArray_Byteswap(range, 1); | ||||||||||||||||
3281 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | ||||||||||||||||
3282 | Py_DECREF(PyArray_DESCR(range))_Py_DECREF(((PyObject*)(PyArray_DESCR(range)))); | ||||||||||||||||
3283 | /* steals the reference */ | ||||||||||||||||
3284 | ((PyArrayObject_fields *)range)->descr = dtype; | ||||||||||||||||
3285 | } | ||||||||||||||||
3286 | Py_DECREF(start)_Py_DECREF(((PyObject*)(start))); | ||||||||||||||||
3287 | Py_DECREF(step)_Py_DECREF(((PyObject*)(step))); | ||||||||||||||||
3288 | Py_DECREF(next)_Py_DECREF(((PyObject*)(next))); | ||||||||||||||||
3289 | return (PyObject *)range; | ||||||||||||||||
3290 | |||||||||||||||||
3291 | fail: | ||||||||||||||||
3292 | Py_DECREF(start)_Py_DECREF(((PyObject*)(start))); | ||||||||||||||||
3293 | Py_DECREF(step)_Py_DECREF(((PyObject*)(step))); | ||||||||||||||||
3294 | Py_XDECREF(next)_Py_XDECREF(((PyObject*)(next))); | ||||||||||||||||
3295 | return NULL((void*)0); | ||||||||||||||||
3296 | } | ||||||||||||||||
3297 | |||||||||||||||||
3298 | /* This array creation function does not steal the reference to dtype. */ | ||||||||||||||||
3299 | static PyArrayObject * | ||||||||||||||||
3300 | array_fromfile_binary(FILE *fp, PyArray_Descr *dtype, npy_intp num, size_t *nread) | ||||||||||||||||
3301 | { | ||||||||||||||||
3302 | PyArrayObject *r; | ||||||||||||||||
3303 | npy_off_toff_t start, numbytes; | ||||||||||||||||
3304 | int elsize; | ||||||||||||||||
3305 | |||||||||||||||||
3306 | if (num < 0) { | ||||||||||||||||
3307 | int fail = 0; | ||||||||||||||||
3308 | start = npy_ftellftello(fp); | ||||||||||||||||
3309 | if (start < 0) { | ||||||||||||||||
3310 | fail = 1; | ||||||||||||||||
3311 | } | ||||||||||||||||
3312 | if (npy_fseekfseeko(fp, 0, SEEK_END2) < 0) { | ||||||||||||||||
3313 | fail = 1; | ||||||||||||||||
3314 | } | ||||||||||||||||
3315 | numbytes = npy_ftellftello(fp); | ||||||||||||||||
3316 | if (numbytes < 0) { | ||||||||||||||||
3317 | fail = 1; | ||||||||||||||||
3318 | } | ||||||||||||||||
3319 | numbytes -= start; | ||||||||||||||||
3320 | if (npy_fseekfseeko(fp, start, SEEK_SET0) < 0) { | ||||||||||||||||
3321 | fail = 1; | ||||||||||||||||
3322 | } | ||||||||||||||||
3323 | if (fail) { | ||||||||||||||||
3324 | PyErr_SetString(PyExc_IOError, | ||||||||||||||||
3325 | "could not seek in file"); | ||||||||||||||||
3326 | return NULL((void*)0); | ||||||||||||||||
3327 | } | ||||||||||||||||
3328 | num = numbytes / dtype->elsize; | ||||||||||||||||
3329 | } | ||||||||||||||||
3330 | |||||||||||||||||
3331 | /* | ||||||||||||||||
3332 | * Array creation may move sub-array dimensions from the dtype to array | ||||||||||||||||
3333 | * dimensions, so we need to use the original element size when reading. | ||||||||||||||||
3334 | */ | ||||||||||||||||
3335 | elsize = dtype->elsize; | ||||||||||||||||
3336 | |||||||||||||||||
3337 | Py_INCREF(dtype)_Py_INCREF(((PyObject*)(dtype))); /* do not steal the original dtype. */ | ||||||||||||||||
3338 | r = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, dtype, 1, &num, | ||||||||||||||||
3339 | NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)); | ||||||||||||||||
3340 | if (r == NULL((void*)0)) { | ||||||||||||||||
3341 | return NULL((void*)0); | ||||||||||||||||
3342 | } | ||||||||||||||||
3343 | |||||||||||||||||
3344 | NPY_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();; | ||||||||||||||||
3345 | *nread = fread(PyArray_DATA(r), elsize, num, fp); | ||||||||||||||||
3346 | NPY_END_ALLOW_THREADSPyEval_RestoreThread(_save); }; | ||||||||||||||||
3347 | return r; | ||||||||||||||||
3348 | } | ||||||||||||||||
3349 | |||||||||||||||||
3350 | /* | ||||||||||||||||
3351 | * Create an array by reading from the given stream, using the passed | ||||||||||||||||
3352 | * next_element and skip_separator functions. | ||||||||||||||||
3353 | * Does not steal the reference to dtype. | ||||||||||||||||
3354 | */ | ||||||||||||||||
3355 | #define FROM_BUFFER_SIZE 4096 | ||||||||||||||||
3356 | static PyArrayObject * | ||||||||||||||||
3357 | array_from_text(PyArray_Descr *dtype, npy_intp num, char const *sep, size_t *nread, | ||||||||||||||||
3358 | void *stream, next_element next, skip_separator skip_sep, | ||||||||||||||||
3359 | void *stream_data) | ||||||||||||||||
3360 | { | ||||||||||||||||
3361 | PyArrayObject *r; | ||||||||||||||||
3362 | npy_intp i; | ||||||||||||||||
3363 | char *dptr, *clean_sep, *tmp; | ||||||||||||||||
3364 | int err = 0; | ||||||||||||||||
3365 | int stop_reading_flag = 0; /* -1 means end reached; -2 a parsing error */ | ||||||||||||||||
3366 | npy_intp thisbuf = 0; | ||||||||||||||||
3367 | npy_intp size; | ||||||||||||||||
3368 | npy_intp bytes, totalbytes; | ||||||||||||||||
3369 | |||||||||||||||||
3370 | size = (num >= 0) ? num : FROM_BUFFER_SIZE; | ||||||||||||||||
3371 | |||||||||||||||||
3372 | /* | ||||||||||||||||
3373 | * Array creation may move sub-array dimensions from the dtype to array | ||||||||||||||||
3374 | * dimensions, so we need to use the original dtype when reading. | ||||||||||||||||
3375 | */ | ||||||||||||||||
3376 | Py_INCREF(dtype)_Py_INCREF(((PyObject*)(dtype))); | ||||||||||||||||
3377 | |||||||||||||||||
3378 | r = (PyArrayObject *) | ||||||||||||||||
3379 | PyArray_NewFromDescr(&PyArray_Type, dtype, 1, &size, | ||||||||||||||||
3380 | NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)); | ||||||||||||||||
3381 | if (r == NULL((void*)0)) { | ||||||||||||||||
3382 | return NULL((void*)0); | ||||||||||||||||
3383 | } | ||||||||||||||||
3384 | |||||||||||||||||
3385 | clean_sep = swab_separator(sep); | ||||||||||||||||
3386 | if (clean_sep == NULL((void*)0)) { | ||||||||||||||||
3387 | err = 1; | ||||||||||||||||
3388 | goto fail; | ||||||||||||||||
3389 | } | ||||||||||||||||
3390 | |||||||||||||||||
3391 | NPY_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();; | ||||||||||||||||
3392 | totalbytes = bytes = size * dtype->elsize; | ||||||||||||||||
3393 | dptr = PyArray_DATA(r); | ||||||||||||||||
3394 | for (i = 0; num < 0 || i < num; i++) { | ||||||||||||||||
3395 | stop_reading_flag = next(&stream, dptr, dtype, stream_data); | ||||||||||||||||
3396 | if (stop_reading_flag < 0) { | ||||||||||||||||
3397 | break; | ||||||||||||||||
3398 | } | ||||||||||||||||
3399 | *nread += 1; | ||||||||||||||||
3400 | thisbuf += 1; | ||||||||||||||||
3401 | dptr += dtype->elsize; | ||||||||||||||||
3402 | if (num < 0 && thisbuf == size) { | ||||||||||||||||
3403 | totalbytes += bytes; | ||||||||||||||||
3404 | tmp = PyDataMem_RENEW(PyArray_DATA(r), totalbytes); | ||||||||||||||||
3405 | if (tmp == NULL((void*)0)) { | ||||||||||||||||
3406 | err = 1; | ||||||||||||||||
3407 | break; | ||||||||||||||||
3408 | } | ||||||||||||||||
3409 | ((PyArrayObject_fields *)r)->data = tmp; | ||||||||||||||||
3410 | dptr = tmp + (totalbytes - bytes); | ||||||||||||||||
3411 | thisbuf = 0; | ||||||||||||||||
3412 | } | ||||||||||||||||
3413 | stop_reading_flag = skip_sep(&stream, clean_sep, stream_data); | ||||||||||||||||
3414 | if (stop_reading_flag < 0) { | ||||||||||||||||
3415 | if (num == i + 1) { | ||||||||||||||||
3416 | /* if we read as much as requested sep is optional */ | ||||||||||||||||
3417 | stop_reading_flag = -1; | ||||||||||||||||
3418 | } | ||||||||||||||||
3419 | break; | ||||||||||||||||
3420 | } | ||||||||||||||||
3421 | } | ||||||||||||||||
3422 | if (num < 0) { | ||||||||||||||||
3423 | const size_t nsize = PyArray_MAX(*nread,1)(((*nread)>(1))?(*nread):(1))*dtype->elsize; | ||||||||||||||||
3424 | |||||||||||||||||
3425 | if (nsize != 0) { | ||||||||||||||||
3426 | tmp = PyDataMem_RENEW(PyArray_DATA(r), nsize); | ||||||||||||||||
3427 | if (tmp == NULL((void*)0)) { | ||||||||||||||||
3428 | err = 1; | ||||||||||||||||
3429 | } | ||||||||||||||||
3430 | else { | ||||||||||||||||
3431 | PyArray_DIMS(r)[0] = *nread; | ||||||||||||||||
3432 | ((PyArrayObject_fields *)r)->data = tmp; | ||||||||||||||||
3433 | } | ||||||||||||||||
3434 | } | ||||||||||||||||
3435 | } | ||||||||||||||||
3436 | NPY_END_ALLOW_THREADSPyEval_RestoreThread(_save); }; | ||||||||||||||||
3437 | |||||||||||||||||
3438 | free(clean_sep); | ||||||||||||||||
3439 | |||||||||||||||||
3440 | if (stop_reading_flag == -2) { | ||||||||||||||||
3441 | if (PyErr_Occurred()) { | ||||||||||||||||
3442 | /* If an error is already set (unlikely), do not create new one */ | ||||||||||||||||
3443 | Py_DECREF(r)_Py_DECREF(((PyObject*)(r))); | ||||||||||||||||
3444 | return NULL((void*)0); | ||||||||||||||||
3445 | } | ||||||||||||||||
3446 | /* 2019-09-12, NumPy 1.18 */ | ||||||||||||||||
3447 | if (DEPRECATE(PyErr_WarnEx(PyExc_DeprecationWarning,"string or file could not be read to its end due to unmatched " "data; this will raise a ValueError in the future.",1) | ||||||||||||||||
3448 | "string or file could not be read to its end due to unmatched "PyErr_WarnEx(PyExc_DeprecationWarning,"string or file could not be read to its end due to unmatched " "data; this will raise a ValueError in the future.",1) | ||||||||||||||||
3449 | "data; this will raise a ValueError in the future.")PyErr_WarnEx(PyExc_DeprecationWarning,"string or file could not be read to its end due to unmatched " "data; this will raise a ValueError in the future.",1) < 0) { | ||||||||||||||||
3450 | goto fail; | ||||||||||||||||
3451 | } | ||||||||||||||||
3452 | } | ||||||||||||||||
3453 | |||||||||||||||||
3454 | fail: | ||||||||||||||||
3455 | if (err == 1) { | ||||||||||||||||
3456 | PyErr_NoMemory(); | ||||||||||||||||
3457 | } | ||||||||||||||||
3458 | if (PyErr_Occurred()) { | ||||||||||||||||
3459 | Py_DECREF(r)_Py_DECREF(((PyObject*)(r))); | ||||||||||||||||
3460 | return NULL((void*)0); | ||||||||||||||||
3461 | } | ||||||||||||||||
3462 | return r; | ||||||||||||||||
3463 | } | ||||||||||||||||
3464 | #undef FROM_BUFFER_SIZE | ||||||||||||||||
3465 | |||||||||||||||||
3466 | /*NUMPY_API | ||||||||||||||||
3467 | * | ||||||||||||||||
3468 | * Given a ``FILE *`` pointer ``fp``, and a ``PyArray_Descr``, return an | ||||||||||||||||
3469 | * array corresponding to the data encoded in that file. | ||||||||||||||||
3470 | * | ||||||||||||||||
3471 | * The reference to `dtype` is stolen (it is possible that the passed in | ||||||||||||||||
3472 | * dtype is not held on to). | ||||||||||||||||
3473 | * | ||||||||||||||||
3474 | * The number of elements to read is given as ``num``; if it is < 0, then | ||||||||||||||||
3475 | * then as many as possible are read. | ||||||||||||||||
3476 | * | ||||||||||||||||
3477 | * If ``sep`` is NULL or empty, then binary data is assumed, else | ||||||||||||||||
3478 | * text data, with ``sep`` as the separator between elements. Whitespace in | ||||||||||||||||
3479 | * the separator matches any length of whitespace in the text, and a match | ||||||||||||||||
3480 | * for whitespace around the separator is added. | ||||||||||||||||
3481 | * | ||||||||||||||||
3482 | * For memory-mapped files, use the buffer interface. No more data than | ||||||||||||||||
3483 | * necessary is read by this routine. | ||||||||||||||||
3484 | */ | ||||||||||||||||
3485 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
3486 | PyArray_FromFile(FILE *fp, PyArray_Descr *dtype, npy_intp num, char *sep) | ||||||||||||||||
3487 | { | ||||||||||||||||
3488 | PyArrayObject *ret; | ||||||||||||||||
3489 | size_t nread = 0; | ||||||||||||||||
3490 | |||||||||||||||||
3491 | if (PyDataType_REFCHK(dtype)(((dtype)->flags & (0x01)) == (0x01))) { | ||||||||||||||||
3492 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3493 | "Cannot read into object array"); | ||||||||||||||||
3494 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3495 | return NULL((void*)0); | ||||||||||||||||
3496 | } | ||||||||||||||||
3497 | if (dtype->elsize == 0) { | ||||||||||||||||
3498 | /* Nothing to read, just create an empty array of the requested type */ | ||||||||||||||||
3499 | return PyArray_NewFromDescr_int( | ||||||||||||||||
3500 | &PyArray_Type, dtype, | ||||||||||||||||
3501 | 1, &num, NULL((void*)0), NULL((void*)0), | ||||||||||||||||
3502 | 0, NULL((void*)0), NULL((void*)0), | ||||||||||||||||
3503 | 0, 1); | ||||||||||||||||
3504 | } | ||||||||||||||||
3505 | if ((sep == NULL((void*)0)) || (strlen(sep) == 0)) { | ||||||||||||||||
3506 | ret = array_fromfile_binary(fp, dtype, num, &nread); | ||||||||||||||||
3507 | } | ||||||||||||||||
3508 | else { | ||||||||||||||||
3509 | if (dtype->f->scanfunc == NULL((void*)0)) { | ||||||||||||||||
3510 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3511 | "Unable to read character files of that array type"); | ||||||||||||||||
3512 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3513 | return NULL((void*)0); | ||||||||||||||||
3514 | } | ||||||||||||||||
3515 | ret = array_from_text(dtype, num, sep, &nread, fp, | ||||||||||||||||
3516 | (next_element) fromfile_next_element, | ||||||||||||||||
3517 | (skip_separator) fromfile_skip_separator, NULL((void*)0)); | ||||||||||||||||
3518 | } | ||||||||||||||||
3519 | if (ret == NULL((void*)0)) { | ||||||||||||||||
3520 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3521 | return NULL((void*)0); | ||||||||||||||||
3522 | } | ||||||||||||||||
3523 | if (((npy_intp) nread) < num) { | ||||||||||||||||
3524 | /* | ||||||||||||||||
3525 | * Realloc memory for smaller number of elements, use original dtype | ||||||||||||||||
3526 | * which may have include a subarray (and is used for `nread`). | ||||||||||||||||
3527 | */ | ||||||||||||||||
3528 | const size_t nsize = PyArray_MAX(nread,1)(((nread)>(1))?(nread):(1)) * dtype->elsize; | ||||||||||||||||
3529 | char *tmp; | ||||||||||||||||
3530 | |||||||||||||||||
3531 | if ((tmp = PyDataMem_RENEW(PyArray_DATA(ret), nsize)) == NULL((void*)0)) { | ||||||||||||||||
3532 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3533 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | ||||||||||||||||
3534 | return PyErr_NoMemory(); | ||||||||||||||||
3535 | } | ||||||||||||||||
3536 | ((PyArrayObject_fields *)ret)->data = tmp; | ||||||||||||||||
3537 | PyArray_DIMS(ret)[0] = nread; | ||||||||||||||||
3538 | } | ||||||||||||||||
3539 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3540 | return (PyObject *)ret; | ||||||||||||||||
3541 | } | ||||||||||||||||
3542 | |||||||||||||||||
3543 | /*NUMPY_API*/ | ||||||||||||||||
3544 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
3545 | PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type, | ||||||||||||||||
3546 | npy_intp count, npy_intp offset) | ||||||||||||||||
3547 | { | ||||||||||||||||
3548 | PyArrayObject *ret; | ||||||||||||||||
3549 | char *data; | ||||||||||||||||
3550 | Py_buffer view; | ||||||||||||||||
3551 | Py_ssize_t ts; | ||||||||||||||||
3552 | npy_intp s, n; | ||||||||||||||||
3553 | int itemsize; | ||||||||||||||||
3554 | int writeable = 1; | ||||||||||||||||
3555 | |||||||||||||||||
3556 | |||||||||||||||||
3557 | if (PyDataType_REFCHK(type)(((type)->flags & (0x01)) == (0x01))) { | ||||||||||||||||
3558 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3559 | "cannot create an OBJECT array from memory"\ | ||||||||||||||||
3560 | " buffer"); | ||||||||||||||||
3561 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | ||||||||||||||||
3562 | return NULL((void*)0); | ||||||||||||||||
3563 | } | ||||||||||||||||
3564 | if (PyDataType_ISUNSIZED(type)((type)->elsize == 0 && !(((PyArray_Descr *)(type) )->names != ((void*)0)))) { | ||||||||||||||||
3565 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3566 | "itemsize cannot be zero in type"); | ||||||||||||||||
3567 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | ||||||||||||||||
3568 | return NULL((void*)0); | ||||||||||||||||
3569 | } | ||||||||||||||||
3570 | |||||||||||||||||
3571 | if (PyObject_GetBuffer(buf, &view, PyBUF_WRITABLE0x0001|PyBUF_SIMPLE0) < 0) { | ||||||||||||||||
3572 | writeable = 0; | ||||||||||||||||
3573 | PyErr_Clear(); | ||||||||||||||||
3574 | if (PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE0) < 0) { | ||||||||||||||||
3575 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | ||||||||||||||||
3576 | return NULL((void*)0); | ||||||||||||||||
3577 | } | ||||||||||||||||
3578 | } | ||||||||||||||||
3579 | data = (char *)view.buf; | ||||||||||||||||
3580 | ts = view.len; | ||||||||||||||||
3581 | /* | ||||||||||||||||
3582 | * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and | ||||||||||||||||
3583 | * PyObject_AsReadBuffer that this code replaces release the buffer. It is | ||||||||||||||||
3584 | * up to the object that supplies the buffer to guarantee that the buffer | ||||||||||||||||
3585 | * sticks around after the release. | ||||||||||||||||
3586 | */ | ||||||||||||||||
3587 | PyBuffer_Release(&view); | ||||||||||||||||
3588 | |||||||||||||||||
3589 | if ((offset < 0) || (offset > ts)) { | ||||||||||||||||
3590 | PyErr_Format(PyExc_ValueError, | ||||||||||||||||
3591 | "offset must be non-negative and no greater than buffer "\ | ||||||||||||||||
3592 | "length (%" NPY_INTP_FMT"ld" ")", (npy_intp)ts); | ||||||||||||||||
3593 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | ||||||||||||||||
3594 | return NULL((void*)0); | ||||||||||||||||
3595 | } | ||||||||||||||||
3596 | |||||||||||||||||
3597 | data += offset; | ||||||||||||||||
3598 | s = (npy_intp)ts - offset; | ||||||||||||||||
3599 | n = (npy_intp)count; | ||||||||||||||||
3600 | itemsize = type->elsize; | ||||||||||||||||
3601 | if (n < 0) { | ||||||||||||||||
3602 | if (itemsize == 0) { | ||||||||||||||||
3603 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3604 | "cannot determine count if itemsize is 0"); | ||||||||||||||||
3605 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | ||||||||||||||||
3606 | return NULL((void*)0); | ||||||||||||||||
3607 | } | ||||||||||||||||
3608 | if (s % itemsize != 0) { | ||||||||||||||||
3609 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3610 | "buffer size must be a multiple"\ | ||||||||||||||||
3611 | " of element size"); | ||||||||||||||||
3612 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | ||||||||||||||||
3613 | return NULL((void*)0); | ||||||||||||||||
3614 | } | ||||||||||||||||
3615 | n = s/itemsize; | ||||||||||||||||
3616 | } | ||||||||||||||||
3617 | else { | ||||||||||||||||
3618 | if (s < n*itemsize) { | ||||||||||||||||
3619 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3620 | "buffer is smaller than requested"\ | ||||||||||||||||
3621 | " size"); | ||||||||||||||||
3622 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | ||||||||||||||||
3623 | return NULL((void*)0); | ||||||||||||||||
3624 | } | ||||||||||||||||
3625 | } | ||||||||||||||||
3626 | |||||||||||||||||
3627 | ret = (PyArrayObject *)PyArray_NewFromDescrAndBase( | ||||||||||||||||
3628 | &PyArray_Type, type, | ||||||||||||||||
3629 | 1, &n, NULL((void*)0), data, | ||||||||||||||||
3630 | NPY_ARRAY_DEFAULT((0x0001 | (0x0100 | 0x0400))), NULL((void*)0), buf); | ||||||||||||||||
3631 | if (ret == NULL((void*)0)) { | ||||||||||||||||
3632 | return NULL((void*)0); | ||||||||||||||||
3633 | } | ||||||||||||||||
3634 | |||||||||||||||||
3635 | if (!writeable) { | ||||||||||||||||
3636 | PyArray_CLEARFLAGS(ret, NPY_ARRAY_WRITEABLE0x0400); | ||||||||||||||||
3637 | } | ||||||||||||||||
3638 | return (PyObject *)ret; | ||||||||||||||||
3639 | } | ||||||||||||||||
3640 | |||||||||||||||||
3641 | /*NUMPY_API | ||||||||||||||||
3642 | * | ||||||||||||||||
3643 | * Given a pointer to a string ``data``, a string length ``slen``, and | ||||||||||||||||
3644 | * a ``PyArray_Descr``, return an array corresponding to the data | ||||||||||||||||
3645 | * encoded in that string. | ||||||||||||||||
3646 | * | ||||||||||||||||
3647 | * If the dtype is NULL, the default array type is used (double). | ||||||||||||||||
3648 | * If non-null, the reference is stolen. | ||||||||||||||||
3649 | * | ||||||||||||||||
3650 | * If ``slen`` is < 0, then the end of string is used for text data. | ||||||||||||||||
3651 | * It is an error for ``slen`` to be < 0 for binary data (since embedded NULLs | ||||||||||||||||
3652 | * would be the norm). | ||||||||||||||||
3653 | * | ||||||||||||||||
3654 | * The number of elements to read is given as ``num``; if it is < 0, then | ||||||||||||||||
3655 | * then as many as possible are read. | ||||||||||||||||
3656 | * | ||||||||||||||||
3657 | * If ``sep`` is NULL or empty, then binary data is assumed, else | ||||||||||||||||
3658 | * text data, with ``sep`` as the separator between elements. Whitespace in | ||||||||||||||||
3659 | * the separator matches any length of whitespace in the text, and a match | ||||||||||||||||
3660 | * for whitespace around the separator is added. | ||||||||||||||||
3661 | */ | ||||||||||||||||
3662 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
3663 | PyArray_FromString(char *data, npy_intp slen, PyArray_Descr *dtype, | ||||||||||||||||
3664 | npy_intp num, char *sep) | ||||||||||||||||
3665 | { | ||||||||||||||||
3666 | int itemsize; | ||||||||||||||||
3667 | PyArrayObject *ret; | ||||||||||||||||
3668 | npy_bool binary; | ||||||||||||||||
3669 | |||||||||||||||||
3670 | if (dtype == NULL((void*)0)) { | ||||||||||||||||
3671 | dtype=PyArray_DescrFromType(NPY_DEFAULT_TYPENPY_DOUBLE); | ||||||||||||||||
3672 | if (dtype == NULL((void*)0)) { | ||||||||||||||||
3673 | return NULL((void*)0); | ||||||||||||||||
3674 | } | ||||||||||||||||
3675 | } | ||||||||||||||||
3676 | if (PyDataType_FLAGCHK(dtype, NPY_ITEM_IS_POINTER)(((dtype)->flags & (0x04)) == (0x04)) || | ||||||||||||||||
3677 | PyDataType_REFCHK(dtype)(((dtype)->flags & (0x01)) == (0x01))) { | ||||||||||||||||
3678 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3679 | "Cannot create an object array from" \ | ||||||||||||||||
3680 | " a string"); | ||||||||||||||||
3681 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3682 | return NULL((void*)0); | ||||||||||||||||
3683 | } | ||||||||||||||||
3684 | itemsize = dtype->elsize; | ||||||||||||||||
3685 | if (itemsize == 0) { | ||||||||||||||||
3686 | PyErr_SetString(PyExc_ValueError, "zero-valued itemsize"); | ||||||||||||||||
3687 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3688 | return NULL((void*)0); | ||||||||||||||||
3689 | } | ||||||||||||||||
3690 | |||||||||||||||||
3691 | binary = ((sep == NULL((void*)0)) || (strlen(sep) == 0)); | ||||||||||||||||
3692 | if (binary) { | ||||||||||||||||
3693 | if (num < 0 ) { | ||||||||||||||||
3694 | if (slen % itemsize != 0) { | ||||||||||||||||
3695 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3696 | "string size must be a "\ | ||||||||||||||||
3697 | "multiple of element size"); | ||||||||||||||||
3698 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3699 | return NULL((void*)0); | ||||||||||||||||
3700 | } | ||||||||||||||||
3701 | num = slen/itemsize; | ||||||||||||||||
3702 | } | ||||||||||||||||
3703 | else { | ||||||||||||||||
3704 | if (slen < num*itemsize) { | ||||||||||||||||
3705 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3706 | "string is smaller than " \ | ||||||||||||||||
3707 | "requested size"); | ||||||||||||||||
3708 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3709 | return NULL((void*)0); | ||||||||||||||||
3710 | } | ||||||||||||||||
3711 | } | ||||||||||||||||
3712 | /* | ||||||||||||||||
3713 | * NewFromDescr may replace dtype to absorb subarray shape | ||||||||||||||||
3714 | * into the array, so get size beforehand. | ||||||||||||||||
3715 | */ | ||||||||||||||||
3716 | npy_intp size_to_copy = num*dtype->elsize; | ||||||||||||||||
3717 | ret = (PyArrayObject *) | ||||||||||||||||
3718 | PyArray_NewFromDescr(&PyArray_Type, dtype, | ||||||||||||||||
3719 | 1, &num, NULL((void*)0), NULL((void*)0), | ||||||||||||||||
3720 | 0, NULL((void*)0)); | ||||||||||||||||
3721 | if (ret == NULL((void*)0)) { | ||||||||||||||||
3722 | return NULL((void*)0); | ||||||||||||||||
3723 | } | ||||||||||||||||
3724 | memcpy(PyArray_DATA(ret), data, size_to_copy); | ||||||||||||||||
3725 | } | ||||||||||||||||
3726 | else { | ||||||||||||||||
3727 | /* read from character-based string */ | ||||||||||||||||
3728 | size_t nread = 0; | ||||||||||||||||
3729 | char *end; | ||||||||||||||||
3730 | |||||||||||||||||
3731 | if (dtype->f->fromstr == NULL((void*)0)) { | ||||||||||||||||
3732 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3733 | "don't know how to read " \ | ||||||||||||||||
3734 | "character strings with that " \ | ||||||||||||||||
3735 | "array type"); | ||||||||||||||||
3736 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3737 | return NULL((void*)0); | ||||||||||||||||
3738 | } | ||||||||||||||||
3739 | if (slen < 0) { | ||||||||||||||||
3740 | end = NULL((void*)0); | ||||||||||||||||
3741 | } | ||||||||||||||||
3742 | else { | ||||||||||||||||
3743 | end = data + slen; | ||||||||||||||||
3744 | } | ||||||||||||||||
3745 | ret = array_from_text(dtype, num, sep, &nread, | ||||||||||||||||
3746 | data, | ||||||||||||||||
3747 | (next_element) fromstr_next_element, | ||||||||||||||||
3748 | (skip_separator) fromstr_skip_separator, | ||||||||||||||||
3749 | end); | ||||||||||||||||
3750 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | ||||||||||||||||
3751 | } | ||||||||||||||||
3752 | return (PyObject *)ret; | ||||||||||||||||
3753 | } | ||||||||||||||||
3754 | |||||||||||||||||
3755 | /*NUMPY_API | ||||||||||||||||
3756 | * | ||||||||||||||||
3757 | * steals a reference to dtype (which cannot be NULL) | ||||||||||||||||
3758 | */ | ||||||||||||||||
3759 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | ||||||||||||||||
3760 | PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count) | ||||||||||||||||
3761 | { | ||||||||||||||||
3762 | PyObject *value; | ||||||||||||||||
3763 | PyObject *iter = PyObject_GetIter(obj); | ||||||||||||||||
3764 | PyArrayObject *ret = NULL((void*)0); | ||||||||||||||||
3765 | npy_intp i, elsize, elcount; | ||||||||||||||||
3766 | char *item, *new_data; | ||||||||||||||||
3767 | |||||||||||||||||
3768 | if (iter == NULL((void*)0)) { | ||||||||||||||||
3769 | goto done; | ||||||||||||||||
3770 | } | ||||||||||||||||
3771 | if (PyDataType_ISUNSIZED(dtype)((dtype)->elsize == 0 && !(((PyArray_Descr *)(dtype ))->names != ((void*)0)))) { | ||||||||||||||||
3772 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3773 | "Must specify length when using variable-size data-type."); | ||||||||||||||||
3774 | goto done; | ||||||||||||||||
3775 | } | ||||||||||||||||
3776 | if (count < 0) { | ||||||||||||||||
3777 | elcount = PyObject_LengthHint(obj, 0); | ||||||||||||||||
3778 | if (elcount < 0) { | ||||||||||||||||
3779 | goto done; | ||||||||||||||||
3780 | } | ||||||||||||||||
3781 | } | ||||||||||||||||
3782 | else { | ||||||||||||||||
3783 | elcount = count; | ||||||||||||||||
3784 | } | ||||||||||||||||
3785 | |||||||||||||||||
3786 | elsize = dtype->elsize; | ||||||||||||||||
3787 | |||||||||||||||||
3788 | /* | ||||||||||||||||
3789 | * We would need to alter the memory RENEW code to decrement any | ||||||||||||||||
3790 | * reference counts before throwing away any memory. | ||||||||||||||||
3791 | */ | ||||||||||||||||
3792 | if (PyDataType_REFCHK(dtype)(((dtype)->flags & (0x01)) == (0x01))) { | ||||||||||||||||
3793 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3794 | "cannot create object arrays from iterator"); | ||||||||||||||||
3795 | goto done; | ||||||||||||||||
3796 | } | ||||||||||||||||
3797 | |||||||||||||||||
3798 | ret = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, dtype, 1, | ||||||||||||||||
3799 | &elcount, NULL((void*)0),NULL((void*)0), 0, NULL((void*)0)); | ||||||||||||||||
3800 | dtype = NULL((void*)0); | ||||||||||||||||
3801 | if (ret == NULL((void*)0)) { | ||||||||||||||||
3802 | goto done; | ||||||||||||||||
3803 | } | ||||||||||||||||
3804 | for (i = 0; (i < count || count == -1) && | ||||||||||||||||
3805 | (value = PyIter_Next(iter)); i++) { | ||||||||||||||||
3806 | if (i >= elcount && elsize != 0) { | ||||||||||||||||
3807 | npy_intp nbytes; | ||||||||||||||||
3808 | /* | ||||||||||||||||
3809 | Grow PyArray_DATA(ret): | ||||||||||||||||
3810 | this is similar for the strategy for PyListObject, but we use | ||||||||||||||||
3811 | 50% overallocation => 0, 4, 8, 14, 23, 36, 56, 86 ... | ||||||||||||||||
3812 | */ | ||||||||||||||||
3813 | elcount = (i >> 1) + (i < 4 ? 4 : 2) + i; | ||||||||||||||||
3814 | if (!npy_mul_with_overflow_intp(&nbytes, elcount, elsize)) { | ||||||||||||||||
3815 | new_data = PyDataMem_RENEW(PyArray_DATA(ret), nbytes); | ||||||||||||||||
3816 | } | ||||||||||||||||
3817 | else { | ||||||||||||||||
3818 | new_data = NULL((void*)0); | ||||||||||||||||
3819 | } | ||||||||||||||||
3820 | if (new_data == NULL((void*)0)) { | ||||||||||||||||
3821 | PyErr_SetString(PyExc_MemoryError, | ||||||||||||||||
3822 | "cannot allocate array memory"); | ||||||||||||||||
3823 | Py_DECREF(value)_Py_DECREF(((PyObject*)(value))); | ||||||||||||||||
3824 | goto done; | ||||||||||||||||
3825 | } | ||||||||||||||||
3826 | ((PyArrayObject_fields *)ret)->data = new_data; | ||||||||||||||||
3827 | } | ||||||||||||||||
3828 | PyArray_DIMS(ret)[0] = i + 1; | ||||||||||||||||
3829 | |||||||||||||||||
3830 | if (((item = index2ptr(ret, i)) == NULL((void*)0)) || | ||||||||||||||||
3831 | PyArray_SETITEM(ret, item, value) == -1) { | ||||||||||||||||
3832 | Py_DECREF(value)_Py_DECREF(((PyObject*)(value))); | ||||||||||||||||
3833 | goto done; | ||||||||||||||||
3834 | } | ||||||||||||||||
3835 | Py_DECREF(value)_Py_DECREF(((PyObject*)(value))); | ||||||||||||||||
3836 | } | ||||||||||||||||
3837 | |||||||||||||||||
3838 | |||||||||||||||||
3839 | if (PyErr_Occurred()) { | ||||||||||||||||
3840 | goto done; | ||||||||||||||||
3841 | } | ||||||||||||||||
3842 | if (i < count) { | ||||||||||||||||
3843 | PyErr_SetString(PyExc_ValueError, | ||||||||||||||||
3844 | "iterator too short"); | ||||||||||||||||
3845 | goto done; | ||||||||||||||||
3846 | } | ||||||||||||||||
3847 | |||||||||||||||||
3848 | /* | ||||||||||||||||
3849 | * Realloc the data so that don't keep extra memory tied up | ||||||||||||||||
3850 | * (assuming realloc is reasonably good about reusing space...) | ||||||||||||||||
3851 | */ | ||||||||||||||||
3852 | if (i == 0 || elsize == 0) { | ||||||||||||||||
3853 | /* The size cannot be zero for PyDataMem_RENEW. */ | ||||||||||||||||
3854 | goto done; | ||||||||||||||||
3855 | } | ||||||||||||||||
3856 | new_data = PyDataMem_RENEW(PyArray_DATA(ret), i * elsize); | ||||||||||||||||
3857 | if (new_data == NULL((void*)0)) { | ||||||||||||||||
3858 | PyErr_SetString(PyExc_MemoryError, | ||||||||||||||||
3859 | "cannot allocate array memory"); | ||||||||||||||||
3860 | goto done; | ||||||||||||||||
3861 | } | ||||||||||||||||
3862 | ((PyArrayObject_fields *)ret)->data = new_data; | ||||||||||||||||
3863 | |||||||||||||||||
3864 | done: | ||||||||||||||||
3865 | Py_XDECREF(iter)_Py_XDECREF(((PyObject*)(iter))); | ||||||||||||||||
3866 | Py_XDECREF(dtype)_Py_XDECREF(((PyObject*)(dtype))); | ||||||||||||||||
3867 | if (PyErr_Occurred()) { | ||||||||||||||||
3868 | Py_XDECREF(ret)_Py_XDECREF(((PyObject*)(ret))); | ||||||||||||||||
3869 | return NULL((void*)0); | ||||||||||||||||
3870 | } | ||||||||||||||||
3871 | return (PyObject *)ret; | ||||||||||||||||
3872 | } | ||||||||||||||||
3873 | |||||||||||||||||
3874 | /* | ||||||||||||||||
3875 | * This is the main array creation routine. | ||||||||||||||||
3876 | * | ||||||||||||||||
3877 | * Flags argument has multiple related meanings | ||||||||||||||||
3878 | * depending on data and strides: | ||||||||||||||||
3879 | * | ||||||||||||||||
3880 | * If data is given, then flags is flags associated with data. | ||||||||||||||||
3881 | * If strides is not given, then a contiguous strides array will be created | ||||||||||||||||
3882 | * and the NPY_ARRAY_C_CONTIGUOUS bit will be set. If the flags argument | ||||||||||||||||
3883 | * has the NPY_ARRAY_F_CONTIGUOUS bit set, then a FORTRAN-style strides array will be | ||||||||||||||||
3884 | * created (and of course the NPY_ARRAY_F_CONTIGUOUS flag bit will be set). | ||||||||||||||||
3885 | * | ||||||||||||||||
3886 | * If data is not given but created here, then flags will be NPY_ARRAY_DEFAULT | ||||||||||||||||
3887 | * and a non-zero flags argument can be used to indicate a FORTRAN style | ||||||||||||||||
3888 | * array is desired. | ||||||||||||||||
3889 | * | ||||||||||||||||
3890 | * Dimensions and itemsize must have been checked for validity. | ||||||||||||||||
3891 | */ | ||||||||||||||||
3892 | |||||||||||||||||
3893 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) void | ||||||||||||||||
3894 | _array_fill_strides(npy_intp *strides, npy_intp const *dims, int nd, size_t itemsize, | ||||||||||||||||
3895 | int inflag, int *objflags) | ||||||||||||||||
3896 | { | ||||||||||||||||
3897 | int i; | ||||||||||||||||
3898 | #if NPY_RELAXED_STRIDES_CHECKING1 | ||||||||||||||||
3899 | npy_bool not_cf_contig = 0; | ||||||||||||||||
3900 | npy_bool nod = 0; /* A dim != 1 was found */ | ||||||||||||||||
3901 | |||||||||||||||||
3902 | /* Check if new array is both F- and C-contiguous */ | ||||||||||||||||
3903 | for (i = 0; i < nd; i++) { | ||||||||||||||||
3904 | if (dims[i] != 1) { | ||||||||||||||||
3905 | if (nod) { | ||||||||||||||||
3906 | not_cf_contig = 1; | ||||||||||||||||
3907 | break; | ||||||||||||||||
3908 | } | ||||||||||||||||
3909 | nod = 1; | ||||||||||||||||
3910 | } | ||||||||||||||||
3911 | } | ||||||||||||||||
3912 | #endif /* NPY_RELAXED_STRIDES_CHECKING */ | ||||||||||||||||
3913 | |||||||||||||||||
3914 | /* Only make Fortran strides if not contiguous as well */ | ||||||||||||||||
3915 | if ((inflag & (NPY_ARRAY_F_CONTIGUOUS0x0002|NPY_ARRAY_C_CONTIGUOUS0x0001)) == | ||||||||||||||||
3916 | NPY_ARRAY_F_CONTIGUOUS0x0002) { | ||||||||||||||||
3917 | for (i = 0; i < nd; i++) { | ||||||||||||||||
3918 | strides[i] = itemsize; | ||||||||||||||||
3919 | if (dims[i]) { | ||||||||||||||||
3920 | itemsize *= dims[i]; | ||||||||||||||||
3921 | } | ||||||||||||||||
3922 | #if NPY_RELAXED_STRIDES_CHECKING1 | ||||||||||||||||
3923 | else { | ||||||||||||||||
3924 | not_cf_contig = 0; | ||||||||||||||||
3925 | } | ||||||||||||||||
3926 | #if NPY_RELAXED_STRIDES_DEBUG0 | ||||||||||||||||
3927 | /* For testing purpose only */ | ||||||||||||||||
3928 | if (dims[i] == 1) { | ||||||||||||||||
3929 | strides[i] = NPY_MAX_INTP9223372036854775807L; | ||||||||||||||||
3930 | } | ||||||||||||||||
3931 | #endif /* NPY_RELAXED_STRIDES_DEBUG */ | ||||||||||||||||
3932 | #endif /* NPY_RELAXED_STRIDES_CHECKING */ | ||||||||||||||||
3933 | } | ||||||||||||||||
3934 | #if NPY_RELAXED_STRIDES_CHECKING1 | ||||||||||||||||
3935 | if (not_cf_contig) { | ||||||||||||||||
3936 | #else /* not NPY_RELAXED_STRIDES_CHECKING */ | ||||||||||||||||
3937 | if ((nd > 1) && ((strides[0] != strides[nd-1]) || (dims[nd-1] > 1))) { | ||||||||||||||||
3938 | #endif /* not NPY_RELAXED_STRIDES_CHECKING */ | ||||||||||||||||
3939 | *objflags = ((*objflags)|NPY_ARRAY_F_CONTIGUOUS0x0002) & | ||||||||||||||||
3940 | ~NPY_ARRAY_C_CONTIGUOUS0x0001; | ||||||||||||||||
3941 | } | ||||||||||||||||
3942 | else { | ||||||||||||||||
3943 | *objflags |= (NPY_ARRAY_F_CONTIGUOUS0x0002|NPY_ARRAY_C_CONTIGUOUS0x0001); | ||||||||||||||||
3944 | } | ||||||||||||||||
3945 | } | ||||||||||||||||
3946 | else { | ||||||||||||||||
3947 | for (i = nd - 1; i >= 0; i--) { | ||||||||||||||||
3948 | strides[i] = itemsize; | ||||||||||||||||
3949 | if (dims[i]) { | ||||||||||||||||
3950 | itemsize *= dims[i]; | ||||||||||||||||
3951 | } | ||||||||||||||||
3952 | #if NPY_RELAXED_STRIDES_CHECKING1 | ||||||||||||||||
3953 | else { | ||||||||||||||||
3954 | not_cf_contig = 0; | ||||||||||||||||
3955 | } | ||||||||||||||||
3956 | #if NPY_RELAXED_STRIDES_DEBUG0 | ||||||||||||||||
3957 | /* For testing purpose only */ | ||||||||||||||||
3958 | if (dims[i] == 1) { | ||||||||||||||||
3959 | strides[i] = NPY_MAX_INTP9223372036854775807L; | ||||||||||||||||
3960 | } | ||||||||||||||||
3961 | #endif /* NPY_RELAXED_STRIDES_DEBUG */ | ||||||||||||||||
3962 | #endif /* NPY_RELAXED_STRIDES_CHECKING */ | ||||||||||||||||
3963 | } | ||||||||||||||||
3964 | #if NPY_RELAXED_STRIDES_CHECKING1 | ||||||||||||||||
3965 | if (not_cf_contig) { | ||||||||||||||||
3966 | #else /* not NPY_RELAXED_STRIDES_CHECKING */ | ||||||||||||||||
3967 | if ((nd > 1) && ((strides[0] != strides[nd-1]) || (dims[0] > 1))) { | ||||||||||||||||
3968 | #endif /* not NPY_RELAXED_STRIDES_CHECKING */ | ||||||||||||||||
3969 | *objflags = ((*objflags)|NPY_ARRAY_C_CONTIGUOUS0x0001) & | ||||||||||||||||
3970 | ~NPY_ARRAY_F_CONTIGUOUS0x0002; | ||||||||||||||||
3971 | } | ||||||||||||||||
3972 | else { | ||||||||||||||||
3973 | *objflags |= (NPY_ARRAY_C_CONTIGUOUS0x0001|NPY_ARRAY_F_CONTIGUOUS0x0002); | ||||||||||||||||
3974 | } | ||||||||||||||||
3975 | } | ||||||||||||||||
3976 | return; | ||||||||||||||||
3977 | } | ||||||||||||||||
3978 | |||||||||||||||||
3979 | /* | ||||||||||||||||
3980 | * Calls arr_of_subclass.__array_wrap__(towrap), in order to make 'towrap' | ||||||||||||||||
3981 | * have the same ndarray subclass as 'arr_of_subclass'. | ||||||||||||||||
3982 | */ | ||||||||||||||||
3983 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArrayObject * | ||||||||||||||||
3984 | PyArray_SubclassWrap(PyArrayObject *arr_of_subclass, PyArrayObject *towrap) | ||||||||||||||||
3985 | { | ||||||||||||||||
3986 | PyObject *wrapped = PyObject_CallMethod_PyObject_CallMethod_SizeT((PyObject *)arr_of_subclass, | ||||||||||||||||
3987 | "__array_wrap__", "O", towrap); | ||||||||||||||||
3988 | if (wrapped == NULL((void*)0)) { | ||||||||||||||||
3989 | return NULL((void*)0); | ||||||||||||||||
3990 | } | ||||||||||||||||
3991 | if (!PyArray_Check(wrapped)((((PyObject*)(wrapped))->ob_type) == (&PyArray_Type) || PyType_IsSubtype((((PyObject*)(wrapped))->ob_type), (& PyArray_Type)))) { | ||||||||||||||||
3992 | PyErr_SetString(PyExc_RuntimeError, | ||||||||||||||||
3993 | "ndarray subclass __array_wrap__ method returned an " | ||||||||||||||||
3994 | "object which was not an instance of an ndarray subclass"); | ||||||||||||||||
3995 | Py_DECREF(wrapped)_Py_DECREF(((PyObject*)(wrapped))); | ||||||||||||||||
3996 | return NULL((void*)0); | ||||||||||||||||
3997 | } | ||||||||||||||||
3998 | |||||||||||||||||
3999 | return (PyArrayObject *)wrapped; | ||||||||||||||||
4000 | } |
1 | #define NPY_NO_DEPRECATED_API0x0000000E NPY_API_VERSION0x0000000E |
2 | #define _UMATHMODULE |
3 | #define _MULTIARRAYMODULE |
4 | |
5 | #include "Python.h" |
6 | |
7 | #include "numpy/npy_3kcompat.h" |
8 | |
9 | #include "lowlevel_strided_loops.h" |
10 | #include "numpy/arrayobject.h" |
11 | |
12 | #include "descriptor.h" |
13 | #include "convert_datatype.h" |
14 | #include "common_dtype.h" |
15 | #include "dtypemeta.h" |
16 | |
17 | #include "array_coercion.h" |
18 | #include "ctors.h" |
19 | #include "common.h" |
20 | #include "_datetime.h" |
21 | #include "npy_import.h" |
22 | |
23 | |
24 | /* |
25 | * This file defines helpers for some of the ctors.c functions which |
26 | * create an array from Python sequences and types. |
27 | * When creating an array with ``np.array(...)`` we have to do two main things: |
28 | * |
29 | * 1. Find the exact shape of the resulting array |
30 | * 2. Find the correct dtype of the resulting array. |
31 | * |
32 | * In most cases these two things are can be done in a single processing step. |
33 | * There are in principle three different calls that should be distinguished: |
34 | * |
35 | * 1. The user calls ``np.array(..., dtype=np.dtype("<f8"))`` |
36 | * 2. The user calls ``np.array(..., dtype="S")`` |
37 | * 3. The user calls ``np.array(...)`` |
38 | * |
39 | * In the first case, in principle only the shape needs to be found. In the |
40 | * second case, the DType class (e.g. string) is already known but the DType |
41 | * instance (e.g. length of the string) has to be found. |
42 | * In the last case the DType class needs to be found as well. Note that |
43 | * it is not necessary to find the DType class of the entire array, but |
44 | * the DType class needs to be found for each element before the actual |
45 | * dtype instance can be found. |
46 | * |
47 | * Further, there are a few other things to keep in mind when coercing arrays: |
48 | * |
49 | * * For UFunc promotion, Python scalars need to be handled specially to |
50 | * allow value based casting. This requires python complex/float to |
51 | * have their own DTypes. |
52 | * * It is necessary to decide whether or not a sequence is an element. |
53 | * For example tuples are considered elements for structured dtypes, but |
54 | * otherwise are considered sequences. |
55 | * This means that if a dtype is given (either as a class or instance), |
56 | * it can effect the dimension discovery part. |
57 | * For the "special" NumPy types structured void and "c" (single character) |
58 | * this is special cased. For future user-types, this is currently |
59 | * handled by providing calling an `is_known_scalar` method. This method |
60 | * currently ensures that Python numerical types are handled quickly. |
61 | * |
62 | * In the initial version of this implementation, it is assumed that dtype |
63 | * discovery can be implemented sufficiently fast. That is, it is not |
64 | * necessary to create fast paths that only find the correct shape e.g. when |
65 | * ``dtype=np.dtype("f8")`` is given. |
66 | * |
67 | * The code here avoid multiple conversion of array-like objects (including |
68 | * sequences). These objects are cached after conversion, which will require |
69 | * additional memory, but can drastically speed up coercion from from array |
70 | * like objects. |
71 | */ |
72 | |
73 | |
74 | /* |
75 | * For finding a DType quickly from a type, it is easiest to have a |
76 | * a mapping of pytype -> DType. |
77 | * TODO: This mapping means that it is currently impossible to delete a |
78 | * pair of pytype <-> DType. To resolve this, it is necessary to |
79 | * weakly reference the pytype. As long as the pytype is alive, we |
80 | * want to be able to use `np.array([pytype()])`. |
81 | * It should be possible to retrofit this without too much trouble |
82 | * (all type objects support weak references). |
83 | */ |
84 | PyObject *_global_pytype_to_type_dict = NULL((void*)0); |
85 | |
86 | |
87 | /* Enum to track or signal some things during dtype and shape discovery */ |
88 | enum _dtype_discovery_flags { |
89 | FOUND_RAGGED_ARRAY = 1 << 0, |
90 | GAVE_SUBCLASS_WARNING = 1 << 1, |
91 | PROMOTION_FAILED = 1 << 2, |
92 | DISCOVER_STRINGS_AS_SEQUENCES = 1 << 3, |
93 | DISCOVER_TUPLES_AS_ELEMENTS = 1 << 4, |
94 | MAX_DIMS_WAS_REACHED = 1 << 5, |
95 | DESCRIPTOR_WAS_SET = 1 << 6, |
96 | }; |
97 | |
98 | |
99 | /** |
100 | * Adds known sequence types to the global type dictionary, note that when |
101 | * a DType is passed in, this lookup may be ignored. |
102 | * |
103 | * @return -1 on error 0 on success |
104 | */ |
105 | static int |
106 | _prime_global_pytype_to_type_dict(void) |
107 | { |
108 | int res; |
109 | |
110 | /* Add the basic Python sequence types */ |
111 | res = PyDict_SetItem(_global_pytype_to_type_dict, |
112 | (PyObject *)&PyList_Type, Py_None(&_Py_NoneStruct)); |
113 | if (res < 0) { |
114 | return -1; |
115 | } |
116 | res = PyDict_SetItem(_global_pytype_to_type_dict, |
117 | (PyObject *)&PyTuple_Type, Py_None(&_Py_NoneStruct)); |
118 | if (res < 0) { |
119 | return -1; |
120 | } |
121 | /* NumPy Arrays are not handled as scalars */ |
122 | res = PyDict_SetItem(_global_pytype_to_type_dict, |
123 | (PyObject *)&PyArray_Type, Py_None(&_Py_NoneStruct)); |
124 | if (res < 0) { |
125 | return -1; |
126 | } |
127 | return 0; |
128 | } |
129 | |
130 | |
131 | /** |
132 | * Add a new mapping from a python type to the DType class. For a user |
133 | * defined legacy dtype, this function does nothing unless the pytype |
134 | * subclass from `np.generic`. |
135 | * |
136 | * This assumes that the DType class is guaranteed to hold on the |
137 | * python type (this assumption is guaranteed). |
138 | * This functionality supercedes ``_typenum_fromtypeobj``. |
139 | * |
140 | * @param DType DType to map the python type to |
141 | * @param pytype Python type to map from |
142 | * @param userdef Whether or not it is user defined. We ensure that user |
143 | * defined scalars subclass from our scalars (for now). |
144 | */ |
145 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int |
146 | _PyArray_MapPyTypeToDType( |
147 | PyArray_DTypeMeta *DType, PyTypeObject *pytype, npy_bool userdef) |
148 | { |
149 | PyObject *Dtype_obj = (PyObject *)DType; |
150 | |
151 | if (userdef && !PyObject_IsSubclass( |
152 | (PyObject *)pytype, (PyObject *)&PyGenericArrType_Type)) { |
153 | /* |
154 | * We expect that user dtypes (for now) will subclass some numpy |
155 | * scalar class to allow automatic discovery. |
156 | */ |
157 | if (DType->legacy) { |
158 | /* |
159 | * For legacy user dtypes, discovery relied on subclassing, but |
160 | * arbitrary type objects are supported, so do nothing. |
161 | */ |
162 | return 0; |
163 | } |
164 | /* |
165 | * We currently enforce that user DTypes subclass from `np.generic` |
166 | * (this should become a `np.generic` base class and may be lifted |
167 | * entirely). |
168 | */ |
169 | PyErr_Format(PyExc_RuntimeError, |
170 | "currently it is only possible to register a DType " |
171 | "for scalars deriving from `np.generic`, got '%S'.", |
172 | (PyObject *)pytype); |
173 | return -1; |
174 | } |
175 | |
176 | /* Create the global dictionary if it does not exist */ |
177 | if (NPY_UNLIKELY(_global_pytype_to_type_dict == NULL)__builtin_expect(!!(_global_pytype_to_type_dict == ((void*)0) ), 0)) { |
178 | _global_pytype_to_type_dict = PyDict_New(); |
179 | if (_global_pytype_to_type_dict == NULL((void*)0)) { |
180 | return -1; |
181 | } |
182 | if (_prime_global_pytype_to_type_dict() < 0) { |
183 | return -1; |
184 | } |
185 | } |
186 | |
187 | int res = PyDict_Contains(_global_pytype_to_type_dict, (PyObject *)pytype); |
188 | if (res < 0) { |
189 | return -1; |
190 | } |
191 | else if (res) { |
192 | PyErr_SetString(PyExc_RuntimeError, |
193 | "Can only map one python type to DType."); |
194 | return -1; |
195 | } |
196 | |
197 | return PyDict_SetItem(_global_pytype_to_type_dict, |
198 | (PyObject *)pytype, Dtype_obj); |
199 | } |
200 | |
201 | |
202 | /** |
203 | * Lookup the DType for a registered known python scalar type. |
204 | * |
205 | * @param pytype Python Type to look up |
206 | * @return DType, None if it a known non-scalar, or NULL if an unknown object. |
207 | */ |
208 | static NPY_INLINEinline PyArray_DTypeMeta * |
209 | npy_discover_dtype_from_pytype(PyTypeObject *pytype) |
210 | { |
211 | PyObject *DType; |
212 | |
213 | if (pytype == &PyArray_Type) { |
214 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); |
215 | return (PyArray_DTypeMeta *)Py_None(&_Py_NoneStruct); |
216 | } |
217 | |
218 | DType = PyDict_GetItem(_global_pytype_to_type_dict, (PyObject *)pytype); |
219 | if (DType == NULL((void*)0)) { |
220 | /* the python type is not known */ |
221 | return NULL((void*)0); |
222 | } |
223 | |
224 | Py_INCREF(DType)_Py_INCREF(((PyObject*)(DType))); |
225 | if (DType == Py_None(&_Py_NoneStruct)) { |
226 | return (PyArray_DTypeMeta *)Py_None(&_Py_NoneStruct); |
227 | } |
228 | assert(PyObject_TypeCheck(DType, (PyTypeObject *)&PyArrayDTypeMeta_Type))((void) (0)); |
229 | return (PyArray_DTypeMeta *)DType; |
230 | } |
231 | |
232 | |
233 | /** |
234 | * Find the correct DType class for the given python type. If flags is NULL |
235 | * this is not used to discover a dtype, but only for conversion to an |
236 | * existing dtype. In that case the Python (not NumPy) scalar subclass |
237 | * checks are skipped. |
238 | * |
239 | * @param obj The python object, mainly type(pyobj) is used, the object |
240 | * is passed to reuse existing code at this time only. |
241 | * @param flags Flags used to know if warnings were already given. If |
242 | * flags is NULL, this is not |
243 | * @param fixed_DType if not NULL, will be checked first for whether or not |
244 | * it can/wants to handle the (possible) scalar value. |
245 | * @return New reference to either a DType class, Py_None, or NULL on error. |
246 | */ |
247 | static NPY_INLINEinline PyArray_DTypeMeta * |
248 | discover_dtype_from_pyobject( |
249 | PyObject *obj, enum _dtype_discovery_flags *flags, |
250 | PyArray_DTypeMeta *fixed_DType) |
251 | { |
252 | if (fixed_DType != NULL((void*)0)) { |
253 | /* |
254 | * Let the given DType handle the discovery. This is when the |
255 | * scalar-type matches exactly, or the DType signals that it can |
256 | * handle the scalar-type. (Even if it cannot handle here it may be |
257 | * asked to attempt to do so later, if no other matching DType exists.) |
258 | */ |
259 | if ((Py_TYPE(obj)(((PyObject*)(obj))->ob_type) == fixed_DType->scalar_type) || |
260 | (fixed_DType->is_known_scalar_type != NULL((void*)0) && |
261 | fixed_DType->is_known_scalar_type(fixed_DType, Py_TYPE(obj)(((PyObject*)(obj))->ob_type)))) { |
262 | Py_INCREF(fixed_DType)_Py_INCREF(((PyObject*)(fixed_DType))); |
263 | return fixed_DType; |
264 | } |
265 | } |
266 | |
267 | PyArray_DTypeMeta *DType = npy_discover_dtype_from_pytype(Py_TYPE(obj)(((PyObject*)(obj))->ob_type)); |
268 | if (DType != NULL((void*)0)) { |
269 | return DType; |
270 | } |
271 | /* |
272 | * At this point we have not found a clear mapping, but mainly for |
273 | * backward compatibility we have to make some further attempts at |
274 | * interpreting the input as a known scalar type. |
275 | */ |
276 | PyArray_Descr *legacy_descr; |
277 | if (PyArray_IsScalar(obj, Generic)(((((PyObject*)(obj))->ob_type) == (&PyGenericArrType_Type ) || PyType_IsSubtype((((PyObject*)(obj))->ob_type), (& PyGenericArrType_Type))))) { |
278 | legacy_descr = PyArray_DescrFromScalar(obj); |
279 | if (legacy_descr == NULL((void*)0)) { |
280 | return NULL((void*)0); |
281 | } |
282 | } |
283 | else if (flags == NULL((void*)0)) { |
284 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); |
285 | return (PyArray_DTypeMeta *)Py_None(&_Py_NoneStruct); |
286 | } |
287 | else if (PyBytes_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 27))) != 0)) { |
288 | legacy_descr = PyArray_DescrFromType(NPY_BYTE); |
289 | } |
290 | else if (PyUnicode_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { |
291 | legacy_descr = PyArray_DescrFromType(NPY_UNICODE); |
292 | } |
293 | else { |
294 | legacy_descr = _array_find_python_scalar_type(obj); |
295 | } |
296 | |
297 | if (legacy_descr != NULL((void*)0)) { |
298 | DType = NPY_DTYPE(legacy_descr); |
299 | Py_INCREF(DType)_Py_INCREF(((PyObject*)(DType))); |
300 | Py_DECREF(legacy_descr)_Py_DECREF(((PyObject*)(legacy_descr))); |
301 | /* TODO: Enable warning about subclass handling */ |
302 | if ((0) && !((*flags) & GAVE_SUBCLASS_WARNING)) { |
303 | if (DEPRECATE_FUTUREWARNING(PyErr_WarnEx(PyExc_FutureWarning,"in the future NumPy will not automatically find the " "dtype for subclasses of scalars known to NumPy (i.e. " "python types). Use the appropriate `dtype=...` to create " "this array. This will use the `object` dtype or raise " "an error in the future." ,1) |
304 | "in the future NumPy will not automatically find the "PyErr_WarnEx(PyExc_FutureWarning,"in the future NumPy will not automatically find the " "dtype for subclasses of scalars known to NumPy (i.e. " "python types). Use the appropriate `dtype=...` to create " "this array. This will use the `object` dtype or raise " "an error in the future." ,1) |
305 | "dtype for subclasses of scalars known to NumPy (i.e. "PyErr_WarnEx(PyExc_FutureWarning,"in the future NumPy will not automatically find the " "dtype for subclasses of scalars known to NumPy (i.e. " "python types). Use the appropriate `dtype=...` to create " "this array. This will use the `object` dtype or raise " "an error in the future." ,1) |
306 | "python types). Use the appropriate `dtype=...` to create "PyErr_WarnEx(PyExc_FutureWarning,"in the future NumPy will not automatically find the " "dtype for subclasses of scalars known to NumPy (i.e. " "python types). Use the appropriate `dtype=...` to create " "this array. This will use the `object` dtype or raise " "an error in the future." ,1) |
307 | "this array. This will use the `object` dtype or raise "PyErr_WarnEx(PyExc_FutureWarning,"in the future NumPy will not automatically find the " "dtype for subclasses of scalars known to NumPy (i.e. " "python types). Use the appropriate `dtype=...` to create " "this array. This will use the `object` dtype or raise " "an error in the future." ,1) |
308 | "an error in the future.")PyErr_WarnEx(PyExc_FutureWarning,"in the future NumPy will not automatically find the " "dtype for subclasses of scalars known to NumPy (i.e. " "python types). Use the appropriate `dtype=...` to create " "this array. This will use the `object` dtype or raise " "an error in the future." ,1) < 0) { |
309 | return NULL((void*)0); |
310 | } |
311 | *flags |= GAVE_SUBCLASS_WARNING; |
312 | } |
313 | return DType; |
314 | } |
315 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); |
316 | return (PyArray_DTypeMeta *)Py_None(&_Py_NoneStruct); |
317 | } |
318 | |
319 | |
320 | /** |
321 | * Discover the correct descriptor from a known DType class and scalar. |
322 | * If the fixed DType can discover a dtype instance/descr all is fine, |
323 | * if it cannot and DType is used instead, a cast will have to be tried. |
324 | * |
325 | * @param fixed_DType A user provided fixed DType, can be NULL |
326 | * @param DType A discovered DType (by discover_dtype_from_pyobject); |
327 | * this can be identical to `fixed_DType`, if it obj is a |
328 | * known scalar. Can be `NULL` indicating no known type. |
329 | * @param obj The Python scalar object. At the time of calling this function |
330 | * it must be known that `obj` should represent a scalar. |
331 | */ |
332 | static NPY_INLINEinline PyArray_Descr * |
333 | find_scalar_descriptor( |
334 | PyArray_DTypeMeta *fixed_DType, PyArray_DTypeMeta *DType, |
335 | PyObject *obj) |
336 | { |
337 | PyArray_Descr *descr; |
338 | |
339 | if (DType == NULL((void*)0) && fixed_DType == NULL((void*)0)) { |
340 | /* No known DType and no fixed one means we go to object. */ |
341 | return PyArray_DescrFromType(NPY_OBJECT); |
342 | } |
343 | else if (DType == NULL((void*)0)) { |
344 | /* |
345 | * If no DType is known/found, give the fixed give one a second |
346 | * chance. This allows for example string, to call `str(obj)` to |
347 | * figure out the length for arbitrary objects. |
348 | */ |
349 | descr = fixed_DType->discover_descr_from_pyobject(fixed_DType, obj); |
350 | } |
351 | else { |
352 | descr = DType->discover_descr_from_pyobject(DType, obj); |
353 | } |
354 | if (descr == NULL((void*)0)) { |
355 | return NULL((void*)0); |
356 | } |
357 | if (fixed_DType == NULL((void*)0)) { |
358 | return descr; |
359 | } |
360 | |
361 | Py_SETREF(descr, PyArray_CastDescrToDType(descr, fixed_DType))do { PyObject *_py_tmp = ((PyObject*)(descr)); (descr) = (PyArray_CastDescrToDType (descr, fixed_DType)); _Py_DECREF(((PyObject*)(_py_tmp))); } while (0); |
362 | return descr; |
363 | } |
364 | |
365 | |
366 | /** |
367 | * Assign a single element in an array from a python value. |
368 | * |
369 | * The dtypes SETITEM should only be trusted to generally do the right |
370 | * thing if something is known to be a scalar *and* is of a python type known |
371 | * to the DType (which should include all basic Python math types), but in |
372 | * general a cast may be necessary. |
373 | * This function handles the cast, which is for example hit when assigning |
374 | * a float128 to complex128. |
375 | * |
376 | * At this time, this function does not support arrays (historically we |
377 | * mainly supported arrays through `__float__()`, etc.). Such support should |
378 | * possibly be added (although when called from `PyArray_AssignFromCache` |
379 | * the input cannot be an array). |
380 | * Note that this is also problematic for some array-likes, such as |
381 | * `astropy.units.Quantity` and `np.ma.masked`. These are used to us calling |
382 | * `__float__`/`__int__` for 0-D instances in many cases. |
383 | * Eventually, we may want to define this as wrong: They must use DTypes |
384 | * instead of (only) subclasses. Until then, here as well as in |
385 | * `PyArray_AssignFromCache` (which already does this), we need to special |
386 | * case 0-D array-likes to behave like arbitrary (unknown!) Python objects. |
387 | * |
388 | * @param descr |
389 | * @param item |
390 | * @param value |
391 | * @return 0 on success -1 on failure. |
392 | */ |
393 | /* |
394 | * TODO: This function should possibly be public API. |
395 | */ |
396 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int |
397 | PyArray_Pack(PyArray_Descr *descr, char *item, PyObject *value) |
398 | { |
399 | PyArrayObject_fields arr_fields = { |
400 | .flags = NPY_ARRAY_WRITEABLE0x0400, /* assume array is not behaved. */ |
401 | }; |
402 | Py_SET_TYPE(&arr_fields, &PyArray_Type)(((((PyObject*)(&arr_fields))->ob_type) = (&PyArray_Type )), (void)0); |
403 | Py_SET_REFCNT(&arr_fields, 1)(((((PyObject*)(&arr_fields))->ob_refcnt) = (1)), (void )0); |
404 | |
405 | if (NPY_UNLIKELY(descr->type_num == NPY_OBJECT)__builtin_expect(!!(descr->type_num == NPY_OBJECT), 0)) { |
406 | /* |
407 | * We always have store objects directly, casting will lose some |
408 | * type information. Any other dtype discards the type information. |
409 | * TODO: For a Categorical[object] this path may be necessary? |
410 | */ |
411 | arr_fields.descr = descr; |
412 | return descr->f->setitem(value, item, &arr_fields); |
413 | } |
414 | |
415 | /* discover_dtype_from_pyobject includes a check for is_known_scalar_type */ |
416 | PyArray_DTypeMeta *DType = discover_dtype_from_pyobject( |
417 | value, NULL((void*)0), NPY_DTYPE(descr)); |
418 | if (DType == NULL((void*)0)) { |
419 | return -1; |
420 | } |
421 | if (DType == NPY_DTYPE(descr) || DType == (PyArray_DTypeMeta *)Py_None(&_Py_NoneStruct)) { |
422 | /* We can set the element directly (or at least will try to) */ |
423 | Py_XDECREF(DType)_Py_XDECREF(((PyObject*)(DType))); |
424 | arr_fields.descr = descr; |
425 | return descr->f->setitem(value, item, &arr_fields); |
426 | } |
427 | PyArray_Descr *tmp_descr; |
428 | tmp_descr = DType->discover_descr_from_pyobject(DType, value); |
429 | Py_DECREF(DType)_Py_DECREF(((PyObject*)(DType))); |
430 | if (tmp_descr == NULL((void*)0)) { |
431 | return -1; |
432 | } |
433 | |
434 | char *data = PyObject_Malloc(tmp_descr->elsize); |
435 | if (data == NULL((void*)0)) { |
436 | PyErr_NoMemory(); |
437 | Py_DECREF(tmp_descr)_Py_DECREF(((PyObject*)(tmp_descr))); |
438 | return -1; |
439 | } |
440 | if (PyDataType_FLAGCHK(tmp_descr, NPY_NEEDS_INIT)(((tmp_descr)->flags & (0x08)) == (0x08))) { |
441 | memset(data, 0, tmp_descr->elsize); |
442 | } |
443 | arr_fields.descr = tmp_descr; |
444 | if (tmp_descr->f->setitem(value, data, &arr_fields) < 0) { |
445 | PyObject_Free(data); |
446 | Py_DECREF(tmp_descr)_Py_DECREF(((PyObject*)(tmp_descr))); |
447 | return -1; |
448 | } |
449 | if (PyDataType_REFCHK(tmp_descr)(((tmp_descr)->flags & (0x01)) == (0x01))) { |
450 | /* We could probably use move-references above */ |
451 | PyArray_Item_INCREF(data, tmp_descr); |
452 | } |
453 | |
454 | int res = 0; |
455 | int needs_api = 0; |
456 | NPY_cast_info cast_info; |
457 | if (PyArray_GetDTypeTransferFunction( |
458 | 0, 0, 0, tmp_descr, descr, 0, &cast_info, |
459 | &needs_api) == NPY_FAIL0) { |
460 | res = -1; |
461 | goto finish; |
462 | } |
463 | char *args[2] = {data, item}; |
464 | const npy_intp strides[2] = {0, 0}; |
465 | const npy_intp length = 1; |
466 | if (cast_info.func(&cast_info.context, |
467 | args, &length, strides, cast_info.auxdata) < 0) { |
468 | res = -1; |
469 | } |
470 | NPY_cast_info_xfree(&cast_info); |
471 | |
472 | finish: |
473 | if (PyDataType_REFCHK(tmp_descr)(((tmp_descr)->flags & (0x01)) == (0x01))) { |
474 | /* We could probably use move-references above */ |
475 | PyArray_Item_XDECREF(data, tmp_descr); |
476 | } |
477 | PyObject_Free(data); |
478 | Py_DECREF(tmp_descr)_Py_DECREF(((PyObject*)(tmp_descr))); |
479 | return res; |
480 | } |
481 | |
482 | |
483 | static int |
484 | update_shape(int curr_ndim, int *max_ndim, |
485 | npy_intp out_shape[NPY_MAXDIMS32], int new_ndim, |
486 | const npy_intp new_shape[NPY_MAXDIMS32], npy_bool sequence, |
487 | enum _dtype_discovery_flags *flags) |
488 | { |
489 | int success = 0; /* unsuccessful if array is ragged */ |
490 | const npy_bool max_dims_reached = *flags & MAX_DIMS_WAS_REACHED; |
491 | |
492 | if (curr_ndim + new_ndim > *max_ndim) { |
493 | success = -1; |
494 | /* Only update/check as many dims as possible, max_ndim is unchanged */ |
495 | new_ndim = *max_ndim - curr_ndim; |
496 | } |
497 | else if (!sequence && (*max_ndim != curr_ndim + new_ndim)) { |
498 | /* |
499 | * Sequences do not update max_ndim, otherwise shrink and check. |
500 | * This is depth first, so if it is already set, `out_shape` is filled. |
501 | */ |
502 | *max_ndim = curr_ndim + new_ndim; |
503 | /* If a shape was already set, this is also ragged */ |
504 | if (max_dims_reached) { |
505 | success = -1; |
506 | } |
507 | } |
508 | for (int i = 0; i < new_ndim; i++) { |
509 | npy_intp curr_dim = out_shape[curr_ndim + i]; |
510 | npy_intp new_dim = new_shape[i]; |
511 | |
512 | if (!max_dims_reached) { |
513 | out_shape[curr_ndim + i] = new_dim; |
514 | } |
515 | else if (new_dim != curr_dim) { |
516 | /* The array is ragged, and this dimension is unusable already */ |
517 | success = -1; |
518 | if (!sequence) { |
519 | /* Remove dimensions that we cannot use: */ |
520 | *max_ndim -= new_ndim - i; |
521 | } |
522 | else { |
523 | assert(i == 0)((void) (0)); |
524 | /* max_ndim is usually not updated for sequences, so set now: */ |
525 | *max_ndim = curr_ndim; |
526 | } |
527 | break; |
528 | } |
529 | } |
530 | if (!sequence) { |
531 | *flags |= MAX_DIMS_WAS_REACHED; |
532 | } |
533 | return success; |
534 | } |
535 | |
536 | |
537 | #define COERCION_CACHE_CACHE_SIZE 5 |
538 | static int _coercion_cache_num = 0; |
539 | static coercion_cache_obj *_coercion_cache_cache[COERCION_CACHE_CACHE_SIZE]; |
540 | |
541 | /* |
542 | * Steals a reference to the object. |
543 | */ |
544 | static NPY_INLINEinline int |
545 | npy_new_coercion_cache( |
546 | PyObject *converted_obj, PyObject *arr_or_sequence, npy_bool sequence, |
547 | coercion_cache_obj ***next_ptr, int ndim) |
548 | { |
549 | coercion_cache_obj *cache; |
550 | if (_coercion_cache_num > 0) { |
551 | _coercion_cache_num--; |
552 | cache = _coercion_cache_cache[_coercion_cache_num]; |
553 | } |
554 | else { |
555 | cache = PyMem_Malloc(sizeof(coercion_cache_obj)); |
556 | } |
557 | if (cache == NULL((void*)0)) { |
558 | PyErr_NoMemory(); |
559 | return -1; |
560 | } |
561 | cache->converted_obj = converted_obj; |
562 | cache->arr_or_sequence = arr_or_sequence; |
563 | cache->sequence = sequence; |
564 | cache->depth = ndim; |
565 | cache->next = NULL((void*)0); |
566 | **next_ptr = cache; |
567 | *next_ptr = &(cache->next); |
568 | return 0; |
569 | } |
570 | |
571 | /** |
572 | * Unlink coercion cache item. |
573 | * |
574 | * @param current |
575 | * @return next coercion cache object (or NULL) |
576 | */ |
577 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) coercion_cache_obj * |
578 | npy_unlink_coercion_cache(coercion_cache_obj *current) |
579 | { |
580 | coercion_cache_obj *next = current->next; |
581 | Py_DECREF(current->arr_or_sequence)_Py_DECREF(((PyObject*)(current->arr_or_sequence))); |
582 | if (_coercion_cache_num < COERCION_CACHE_CACHE_SIZE) { |
583 | _coercion_cache_cache[_coercion_cache_num] = current; |
584 | _coercion_cache_num++; |
585 | } |
586 | else { |
587 | PyMem_Free(current); |
588 | } |
589 | return next; |
590 | } |
591 | |
592 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) void |
593 | npy_free_coercion_cache(coercion_cache_obj *next) { |
594 | /* We only need to check from the last used cache pos */ |
595 | while (next != NULL((void*)0)) { |
596 | next = npy_unlink_coercion_cache(next); |
597 | } |
598 | } |
599 | |
600 | #undef COERCION_CACHE_CACHE_SIZE |
601 | |
602 | /** |
603 | * Do the promotion step and possible casting. This function should |
604 | * never be called if a descriptor was requested. In that case the output |
605 | * dtype is not of importance, so we must not risk promotion errors. |
606 | * |
607 | * @param out_descr The current descriptor. |
608 | * @param descr The newly found descriptor to promote with |
609 | * @param fixed_DType The user provided (fixed) DType or NULL |
610 | * @param flags dtype discover flags to signal failed promotion. |
611 | * @return -1 on error, 0 on success. |
612 | */ |
613 | static NPY_INLINEinline int |
614 | handle_promotion(PyArray_Descr **out_descr, PyArray_Descr *descr, |
615 | PyArray_DTypeMeta *fixed_DType, enum _dtype_discovery_flags *flags) |
616 | { |
617 | assert(!(*flags & DESCRIPTOR_WAS_SET))((void) (0)); |
618 | |
619 | if (*out_descr == NULL((void*)0)) { |
620 | Py_INCREF(descr)_Py_INCREF(((PyObject*)(descr))); |
621 | *out_descr = descr; |
622 | return 0; |
623 | } |
624 | PyArray_Descr *new_descr = PyArray_PromoteTypes(descr, *out_descr); |
625 | if (NPY_UNLIKELY(new_descr == NULL)__builtin_expect(!!(new_descr == ((void*)0)), 0)) { |
626 | if (fixed_DType != NULL((void*)0) || PyErr_ExceptionMatches(PyExc_FutureWarning)) { |
627 | /* |
628 | * If a DType is fixed, promotion must not fail. Do not catch |
629 | * FutureWarning (raised for string+numeric promotions). We could |
630 | * only catch TypeError here or even always raise the error. |
631 | */ |
632 | return -1; |
633 | } |
634 | PyErr_Clear(); |
635 | *flags |= PROMOTION_FAILED; |
636 | /* Continue with object, since we may need the dimensionality */ |
637 | new_descr = PyArray_DescrFromType(NPY_OBJECT); |
638 | } |
639 | Py_SETREF(*out_descr, new_descr)do { PyObject *_py_tmp = ((PyObject*)(*out_descr)); (*out_descr ) = (new_descr); _Py_DECREF(((PyObject*)(_py_tmp))); } while ( 0); |
640 | return 0; |
641 | } |
642 | |
643 | |
644 | /** |
645 | * Handle a leave node (known scalar) during dtype and shape discovery. |
646 | * |
647 | * @param obj The python object or nested sequence to convert |
648 | * @param curr_dims The current number of dimensions (depth in the recursion) |
649 | * @param max_dims The maximum number of dimensions. |
650 | * @param out_shape The discovered output shape, will be filled |
651 | * @param fixed_DType The user provided (fixed) DType or NULL |
652 | * @param flags used signal that this is a ragged array, used internally and |
653 | * can be expanded if necessary. |
654 | * @param DType the DType class that should be used, or NULL, if not provided. |
655 | * |
656 | * @return 0 on success -1 on error |
657 | */ |
658 | static NPY_INLINEinline int |
659 | handle_scalar( |
660 | PyObject *obj, int curr_dims, int *max_dims, |
661 | PyArray_Descr **out_descr, npy_intp *out_shape, |
662 | PyArray_DTypeMeta *fixed_DType, |
663 | enum _dtype_discovery_flags *flags, PyArray_DTypeMeta *DType) |
664 | { |
665 | PyArray_Descr *descr; |
666 | |
667 | if (update_shape(curr_dims, max_dims, out_shape, |
668 | 0, NULL((void*)0), NPY_FALSE0, flags) < 0) { |
669 | *flags |= FOUND_RAGGED_ARRAY; |
670 | return *max_dims; |
671 | } |
672 | if (*flags & DESCRIPTOR_WAS_SET) { |
673 | /* no need to do any promotion */ |
674 | return *max_dims; |
675 | } |
676 | /* This is a scalar, so find the descriptor */ |
677 | descr = find_scalar_descriptor(fixed_DType, DType, obj); |
678 | if (descr == NULL((void*)0)) { |
679 | return -1; |
680 | } |
681 | if (handle_promotion(out_descr, descr, fixed_DType, flags) < 0) { |
682 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); |
683 | return -1; |
684 | } |
685 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); |
686 | return *max_dims; |
687 | } |
688 | |
689 | |
690 | /** |
691 | * Return the correct descriptor given an array object and a DType class. |
692 | * |
693 | * This is identical to casting the arrays descriptor/dtype to the new |
694 | * DType class |
695 | * |
696 | * @param arr The array object. |
697 | * @param DType The DType class to cast to (or NULL for convenience) |
698 | * @param out_descr The output descriptor will set. The result can be NULL |
699 | * when the array is of object dtype and has no elements. |
700 | * |
701 | * @return -1 on failure, 0 on success. |
702 | */ |
703 | static int |
704 | find_descriptor_from_array( |
705 | PyArrayObject *arr, PyArray_DTypeMeta *DType, PyArray_Descr **out_descr) |
706 | { |
707 | enum _dtype_discovery_flags flags = 0; |
708 | *out_descr = NULL((void*)0); |
709 | |
710 | if (DType == NULL((void*)0)) { |
711 | *out_descr = PyArray_DESCR(arr); |
712 | Py_INCREF(*out_descr)_Py_INCREF(((PyObject*)(*out_descr))); |
713 | return 0; |
714 | } |
715 | |
716 | if (NPY_UNLIKELY(DType->parametric && PyArray_ISOBJECT(arr))__builtin_expect(!!(DType->parametric && ((PyArray_TYPE (arr)) == NPY_OBJECT)), 0)) { |
717 | /* |
718 | * We have one special case, if (and only if) the input array is of |
719 | * object DType and the dtype is not fixed already but parametric. |
720 | * Then, we allow inspection of all elements, treating them as |
721 | * elements. We do this recursively, so nested 0-D arrays can work, |
722 | * but nested higher dimensional arrays will lead to an error. |
723 | */ |
724 | assert(DType->type_num != NPY_OBJECT)((void) (0)); /* not parametric */ |
725 | |
726 | PyArrayIterObject *iter; |
727 | iter = (PyArrayIterObject *)PyArray_IterNew((PyObject *)arr); |
728 | if (iter == NULL((void*)0)) { |
729 | return -1; |
730 | } |
731 | while (iter->index < iter->size) { |
732 | PyArray_DTypeMeta *item_DType; |
733 | /* |
734 | * Note: If the array contains typed objects we may need to use |
735 | * the dtype to use casting for finding the correct instance. |
736 | */ |
737 | PyObject *elem = PyArray_GETITEM(arr, iter->dataptr); |
738 | if (elem == NULL((void*)0)) { |
739 | Py_DECREF(iter)_Py_DECREF(((PyObject*)(iter))); |
740 | return -1; |
741 | } |
742 | item_DType = discover_dtype_from_pyobject(elem, &flags, DType); |
743 | if (item_DType == NULL((void*)0)) { |
744 | Py_DECREF(iter)_Py_DECREF(((PyObject*)(iter))); |
745 | Py_DECREF(elem)_Py_DECREF(((PyObject*)(elem))); |
746 | return -1; |
747 | } |
748 | if (item_DType == (PyArray_DTypeMeta *)Py_None(&_Py_NoneStruct)) { |
749 | Py_SETREF(item_DType, NULL)do { PyObject *_py_tmp = ((PyObject*)(item_DType)); (item_DType ) = (((void*)0)); _Py_DECREF(((PyObject*)(_py_tmp))); } while (0); |
750 | } |
751 | int flat_max_dims = 0; |
752 | if (handle_scalar(elem, 0, &flat_max_dims, out_descr, |
753 | NULL((void*)0), DType, &flags, item_DType) < 0) { |
754 | Py_DECREF(iter)_Py_DECREF(((PyObject*)(iter))); |
755 | Py_DECREF(elem)_Py_DECREF(((PyObject*)(elem))); |
756 | Py_XDECREF(*out_descr)_Py_XDECREF(((PyObject*)(*out_descr))); |
757 | Py_XDECREF(item_DType)_Py_XDECREF(((PyObject*)(item_DType))); |
758 | return -1; |
759 | } |
760 | Py_XDECREF(item_DType)_Py_XDECREF(((PyObject*)(item_DType))); |
761 | Py_DECREF(elem)_Py_DECREF(((PyObject*)(elem))); |
762 | PyArray_ITER_NEXT(iter)do { ((PyArrayIterObject *)(iter))->index++; if (((PyArrayIterObject *)(iter))->nd_m1 == 0) { do { (((PyArrayIterObject *)(iter )))->dataptr += ((PyArrayIterObject *)(((PyArrayIterObject *)(iter))))->strides[0]; (((PyArrayIterObject *)(iter)))-> coordinates[0]++; } while (0); } else if (((PyArrayIterObject *)(iter))->contiguous) ((PyArrayIterObject *)(iter))-> dataptr += PyArray_DESCR(((PyArrayIterObject *)(iter))->ao )->elsize; else if (((PyArrayIterObject *)(iter))->nd_m1 == 1) { do { if ((((PyArrayIterObject *)(iter)))->coordinates [1] < (((PyArrayIterObject *)(iter)))->dims_m1[1]) { (( (PyArrayIterObject *)(iter)))->coordinates[1]++; (((PyArrayIterObject *)(iter)))->dataptr += (((PyArrayIterObject *)(iter)))-> strides[1]; } else { (((PyArrayIterObject *)(iter)))->coordinates [1] = 0; (((PyArrayIterObject *)(iter)))->coordinates[0]++ ; (((PyArrayIterObject *)(iter)))->dataptr += (((PyArrayIterObject *)(iter)))->strides[0] - (((PyArrayIterObject *)(iter)))-> backstrides[1]; } } while (0); } else { int __npy_i; for (__npy_i =((PyArrayIterObject *)(iter))->nd_m1; __npy_i >= 0; __npy_i --) { if (((PyArrayIterObject *)(iter))->coordinates[__npy_i ] < ((PyArrayIterObject *)(iter))->dims_m1[__npy_i]) { ( (PyArrayIterObject *)(iter))->coordinates[__npy_i]++; ((PyArrayIterObject *)(iter))->dataptr += ((PyArrayIterObject *)(iter))->strides [__npy_i]; break; } else { ((PyArrayIterObject *)(iter))-> coordinates[__npy_i] = 0; ((PyArrayIterObject *)(iter))->dataptr -= ((PyArrayIterObject *)(iter))->backstrides[__npy_i]; } } } } while (0); |
763 | } |
764 | Py_DECREF(iter)_Py_DECREF(((PyObject*)(iter))); |
765 | } |
766 | else if (NPY_UNLIKELY(DType->type_num == NPY_DATETIME)__builtin_expect(!!(DType->type_num == NPY_DATETIME), 0) && |
767 | PyArray_ISSTRING(arr)(((PyArray_TYPE(arr)) == NPY_STRING) || ((PyArray_TYPE(arr)) == NPY_UNICODE))) { |
768 | /* |
769 | * TODO: This branch should be deprecated IMO, the workaround is |
770 | * to cast to the object to a string array. Although a specific |
771 | * function (if there is even any need) would be better. |
772 | * This is value based casting! |
773 | * Unless of course we actually want to support this kind of thing |
774 | * in general (not just for object dtype)... |
775 | */ |
776 | PyArray_DatetimeMetaData meta; |
777 | meta.base = NPY_FR_GENERIC; |
778 | meta.num = 1; |
779 | |
780 | if (find_string_array_datetime64_type(arr, &meta) < 0) { |
781 | return -1; |
782 | } |
783 | else { |
784 | *out_descr = create_datetime_dtype(NPY_DATETIME, &meta); |
785 | if (*out_descr == NULL((void*)0)) { |
786 | return -1; |
787 | } |
788 | } |
789 | } |
790 | else { |
791 | /* |
792 | * If this is not an object array figure out the dtype cast, |
793 | * or simply use the returned DType. |
794 | */ |
795 | *out_descr = PyArray_CastDescrToDType(PyArray_DESCR(arr), DType); |
796 | if (*out_descr == NULL((void*)0)) { |
797 | return -1; |
798 | } |
799 | } |
800 | return 0; |
801 | } |
802 | |
803 | /** |
804 | * Given a dtype or DType object, find the correct descriptor to cast the |
805 | * array to. |
806 | * |
807 | * This function is identical to normal casting using only the dtype, however, |
808 | * it supports inspecting the elements when the array has object dtype |
809 | * (and the given datatype describes a parametric DType class). |
810 | * |
811 | * @param arr |
812 | * @param dtype A dtype instance or class. |
813 | * @return A concrete dtype instance or NULL |
814 | */ |
815 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArray_Descr * |
816 | PyArray_AdaptDescriptorToArray(PyArrayObject *arr, PyObject *dtype) |
817 | { |
818 | /* If the requested dtype is flexible, adapt it */ |
819 | PyArray_Descr *new_dtype; |
820 | PyArray_DTypeMeta *new_DType; |
821 | int res; |
822 | |
823 | res = PyArray_ExtractDTypeAndDescriptor((PyObject *)dtype, |
824 | &new_dtype, &new_DType); |
825 | if (res < 0) { |
826 | return NULL((void*)0); |
827 | } |
828 | if (new_dtype == NULL((void*)0)) { |
829 | res = find_descriptor_from_array(arr, new_DType, &new_dtype); |
830 | if (res < 0) { |
831 | Py_DECREF(new_DType)_Py_DECREF(((PyObject*)(new_DType))); |
832 | return NULL((void*)0); |
833 | } |
834 | if (new_dtype == NULL((void*)0)) { |
835 | /* This is an object array but contained no elements, use default */ |
836 | new_dtype = new_DType->default_descr(new_DType); |
837 | } |
838 | } |
839 | Py_DECREF(new_DType)_Py_DECREF(((PyObject*)(new_DType))); |
840 | return new_dtype; |
841 | } |
842 | |
843 | |
844 | /** |
845 | * Recursion helper for `PyArray_DiscoverDTypeAndShape`. See its |
846 | * documentation for additional details. |
847 | * |
848 | * @param obj The current (possibly nested) object |
849 | * @param curr_dims The current depth, i.e. initially 0 and increasing. |
850 | * @param max_dims Maximum number of dimensions, modified during discovery. |
851 | * @param out_descr dtype instance (or NULL) to promoted and update. |
852 | * @param out_shape The current shape (updated) |
853 | * @param coercion_cache_tail_ptr The tail of the linked list of coercion |
854 | * cache objects, which hold on to converted sequences and arrays. |
855 | * This is a pointer to the `->next` slot of the previous cache so |
856 | * that we can append a new cache object (and update this pointer). |
857 | * (Initially it is a pointer to the user-provided head pointer). |
858 | * @param fixed_DType User provided fixed DType class |
859 | * @param flags Discovery flags (reporting and behaviour flags, see def.) |
860 | * @return The updated number of maximum dimensions (i.e. scalars will set |
861 | * this to the current dimensions). |
862 | */ |
863 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int |
864 | PyArray_DiscoverDTypeAndShape_Recursive( |
865 | PyObject *obj, int curr_dims, int max_dims, PyArray_Descr**out_descr, |
866 | npy_intp out_shape[NPY_MAXDIMS32], |
867 | coercion_cache_obj ***coercion_cache_tail_ptr, |
868 | PyArray_DTypeMeta *fixed_DType, enum _dtype_discovery_flags *flags) |
869 | { |
870 | PyArrayObject *arr = NULL((void*)0); |
871 | PyObject *seq; |
872 | |
873 | /* |
874 | * The first step is to find the DType class if it was not provided, |
875 | * alternatively we have to find out that this is not a scalar at all |
876 | * (which could fail and lead us to `object` dtype). |
877 | */ |
878 | PyArray_DTypeMeta *DType = NULL((void*)0); |
879 | |
880 | if (NPY_UNLIKELY(*flags & DISCOVER_STRINGS_AS_SEQUENCES)__builtin_expect(!!(*flags & DISCOVER_STRINGS_AS_SEQUENCES ), 0)) { |
881 | /* |
882 | * We currently support that bytes/strings are considered sequences, |
883 | * if the dtype is np.dtype('c'), this should be deprecated probably, |
884 | * but requires hacks right now. |
885 | */ |
886 | if (PyBytes_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 27))) != 0) && PyBytes_Size(obj) != 1) { |
887 | goto force_sequence_due_to_char_dtype; |
888 | } |
889 | else if (PyUnicode_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 28))) != 0) && PyUnicode_GetLength(obj) != 1) { |
890 | goto force_sequence_due_to_char_dtype; |
891 | } |
892 | } |
893 | |
894 | /* If this is a known scalar, find the corresponding DType class */ |
895 | DType = discover_dtype_from_pyobject(obj, flags, fixed_DType); |
896 | if (DType == NULL((void*)0)) { |
897 | return -1; |
898 | } |
899 | else if (DType == (PyArray_DTypeMeta *)Py_None(&_Py_NoneStruct)) { |
900 | Py_DECREF(Py_None)_Py_DECREF(((PyObject*)((&_Py_NoneStruct)))); |
901 | } |
902 | else { |
903 | max_dims = handle_scalar( |
904 | obj, curr_dims, &max_dims, out_descr, out_shape, fixed_DType, |
905 | flags, DType); |
906 | Py_DECREF(DType)_Py_DECREF(((PyObject*)(DType))); |
907 | return max_dims; |
908 | } |
909 | |
910 | /* |
911 | * At this point we expect to find either a sequence, or an array-like. |
912 | * Although it is still possible that this fails and we have to use |
913 | * `object`. |
914 | */ |
915 | if (PyArray_Check(obj)((((PyObject*)(obj))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(obj))->ob_type), (&PyArray_Type)))) { |
916 | arr = (PyArrayObject *)obj; |
917 | Py_INCREF(arr)_Py_INCREF(((PyObject*)(arr))); |
918 | } |
919 | else { |
920 | PyArray_Descr *requested_descr = NULL((void*)0); |
921 | if (*flags & DESCRIPTOR_WAS_SET) { |
922 | /* __array__ may be passed the requested descriptor if provided */ |
923 | requested_descr = *out_descr; |
924 | } |
925 | arr = (PyArrayObject *)_array_from_array_like(obj, |
926 | requested_descr, 0, NULL((void*)0)); |
927 | if (arr == NULL((void*)0)) { |
928 | return -1; |
929 | } |
930 | else if (arr == (PyArrayObject *)Py_NotImplemented(&_Py_NotImplementedStruct)) { |
931 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); |
932 | arr = NULL((void*)0); |
933 | } |
934 | else if (curr_dims > 0 && curr_dims != max_dims) { |
935 | /* |
936 | * Deprecated 2020-12-09, NumPy 1.20 |
937 | * |
938 | * See https://github.com/numpy/numpy/issues/17965 |
939 | * Shapely had objects which are not sequences but did export |
940 | * the array-interface (and so are arguably array-like). |
941 | * Previously numpy would not use array-like information during |
942 | * shape discovery, so that it ended up acting as if this was |
943 | * an (unknown) scalar but with the specified dtype. |
944 | * Thus we ignore "scalars" here, as the value stored in the |
945 | * array should be acceptable. |
946 | */ |
947 | if (PyArray_NDIM(arr) > 0 && NPY_UNLIKELY(!PySequence_Check(obj))__builtin_expect(!!(!PySequence_Check(obj)), 0)) { |
948 | if (PyErr_WarnFormat(PyExc_FutureWarning, 1, |
949 | "The input object of type '%s' is an array-like " |
950 | "implementing one of the corresponding protocols " |
951 | "(`__array__`, `__array_interface__` or " |
952 | "`__array_struct__`); but not a sequence (or 0-D). " |
953 | "In the future, this object will be coerced as if it " |
954 | "was first converted using `np.array(obj)`. " |
955 | "To retain the old behaviour, you have to either " |
956 | "modify the type '%s', or assign to an empty array " |
957 | "created with `np.empty(correct_shape, dtype=object)`.", |
958 | Py_TYPE(obj)(((PyObject*)(obj))->ob_type)->tp_name, Py_TYPE(obj)(((PyObject*)(obj))->ob_type)->tp_name) < 0) { |
959 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); |
960 | return -1; |
961 | } |
962 | /* |
963 | * Strangely enough, even though we threw away the result here, |
964 | * we did use it during descriptor discovery, so promote it: |
965 | */ |
966 | if (update_shape(curr_dims, &max_dims, out_shape, |
967 | 0, NULL((void*)0), NPY_FALSE0, flags) < 0) { |
968 | *flags |= FOUND_RAGGED_ARRAY; |
969 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); |
970 | return max_dims; |
971 | } |
972 | if (!(*flags & DESCRIPTOR_WAS_SET) && handle_promotion( |
973 | out_descr, PyArray_DESCR(arr), fixed_DType, flags) < 0) { |
974 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); |
975 | return -1; |
976 | } |
977 | Py_DECREF(arr)_Py_DECREF(((PyObject*)(arr))); |
978 | return max_dims; |
979 | } |
980 | } |
981 | } |
982 | if (arr != NULL((void*)0)) { |
983 | /* |
984 | * This is an array object which will be added to the cache, keeps |
985 | * the reference to the array alive (takes ownership). |
986 | */ |
987 | if (npy_new_coercion_cache(obj, (PyObject *)arr, |
988 | 0, coercion_cache_tail_ptr, curr_dims) < 0) { |
989 | return -1; |
990 | } |
991 | |
992 | if (curr_dims == 0) { |
993 | /* |
994 | * Special case for reverse broadcasting, ignore max_dims if this |
995 | * is a single array-like object; needed for PyArray_CopyObject. |
996 | */ |
997 | memcpy(out_shape, PyArray_SHAPE(arr), |
998 | PyArray_NDIM(arr) * sizeof(npy_intp)); |
999 | max_dims = PyArray_NDIM(arr); |
1000 | } |
1001 | else if (update_shape(curr_dims, &max_dims, out_shape, |
1002 | PyArray_NDIM(arr), PyArray_SHAPE(arr), NPY_FALSE0, flags) < 0) { |
1003 | *flags |= FOUND_RAGGED_ARRAY; |
1004 | return max_dims; |
1005 | } |
1006 | |
1007 | if (*flags & DESCRIPTOR_WAS_SET) { |
1008 | return max_dims; |
1009 | } |
1010 | /* |
1011 | * For arrays we may not just need to cast the dtype to the user |
1012 | * provided fixed_DType. If this is an object array, the elements |
1013 | * may need to be inspected individually. |
1014 | * Note, this finds the descriptor of the array first and only then |
1015 | * promotes here (different associativity). |
1016 | */ |
1017 | PyArray_Descr *cast_descr; |
1018 | if (find_descriptor_from_array(arr, fixed_DType, &cast_descr) < 0) { |
1019 | return -1; |
1020 | } |
1021 | if (cast_descr == NULL((void*)0)) { |
1022 | /* object array with no elements, no need to promote/adjust. */ |
1023 | return max_dims; |
1024 | } |
1025 | if (handle_promotion(out_descr, cast_descr, fixed_DType, flags) < 0) { |
1026 | Py_DECREF(cast_descr)_Py_DECREF(((PyObject*)(cast_descr))); |
1027 | return -1; |
1028 | } |
1029 | Py_DECREF(cast_descr)_Py_DECREF(((PyObject*)(cast_descr))); |
1030 | return max_dims; |
1031 | } |
1032 | |
1033 | /* |
1034 | * The last step is to assume the input should be handled as a sequence |
1035 | * and to handle it recursively. That is, unless we have hit the |
1036 | * dimension limit. |
1037 | */ |
1038 | npy_bool is_sequence = PySequence_Check(obj); |
1039 | if (is_sequence) { |
1040 | is_sequence = PySequence_Size(obj) >= 0; |
1041 | if (NPY_UNLIKELY(!is_sequence)__builtin_expect(!!(!is_sequence), 0)) { |
1042 | /* NOTE: This should likely just raise all errors */ |
1043 | if (PyErr_ExceptionMatches(PyExc_RecursionError) || |
1044 | PyErr_ExceptionMatches(PyExc_MemoryError)) { |
1045 | /* |
1046 | * Consider these unrecoverable errors, continuing execution |
1047 | * might crash the interpreter. |
1048 | */ |
1049 | return -1; |
1050 | } |
1051 | PyErr_Clear(); |
1052 | } |
1053 | } |
1054 | if (NPY_UNLIKELY(*flags & DISCOVER_TUPLES_AS_ELEMENTS)__builtin_expect(!!(*flags & DISCOVER_TUPLES_AS_ELEMENTS) , 0) && |
1055 | PyTuple_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { |
1056 | is_sequence = NPY_FALSE0; |
1057 | } |
1058 | if (curr_dims == max_dims || !is_sequence) { |
1059 | /* Clear any PySequence_Size error which would corrupts further calls */ |
1060 | max_dims = handle_scalar( |
1061 | obj, curr_dims, &max_dims, out_descr, out_shape, fixed_DType, |
1062 | flags, NULL((void*)0)); |
1063 | if (is_sequence) { |
1064 | /* Flag as ragged or too deep array */ |
1065 | *flags |= FOUND_RAGGED_ARRAY; |
1066 | } |
1067 | return max_dims; |
1068 | } |
1069 | /* If we stop supporting bytes/str subclasses, more may be required here: */ |
1070 | assert(!PyBytes_Check(obj) && !PyUnicode_Check(obj))((void) (0)); |
1071 | |
1072 | force_sequence_due_to_char_dtype: |
1073 | |
1074 | /* Ensure we have a sequence (required for PyPy) */ |
1075 | seq = PySequence_Fast(obj, "Could not convert object to sequence"); |
1076 | if (seq == NULL((void*)0)) { |
1077 | /* |
1078 | * Specifically do not fail on things that look like a dictionary, |
1079 | * instead treat them as scalar. |
1080 | */ |
1081 | if (PyErr_ExceptionMatches(PyExc_KeyError)) { |
1082 | PyErr_Clear(); |
1083 | max_dims = handle_scalar( |
1084 | obj, curr_dims, &max_dims, out_descr, out_shape, fixed_DType, |
1085 | flags, NULL((void*)0)); |
1086 | return max_dims; |
1087 | } |
1088 | return -1; |
1089 | } |
1090 | /* The cache takes ownership of the sequence here. */ |
1091 | if (npy_new_coercion_cache(obj, seq, 1, coercion_cache_tail_ptr, curr_dims) < 0) { |
1092 | return -1; |
1093 | } |
1094 | |
1095 | npy_intp size = PySequence_Fast_GET_SIZE(seq)(((((((PyObject*)(seq))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? (((void) (0)), (((PyVarObject*)(seq)) ->ob_size)) : (((PyVarObject*)((((void) (0)), (PyTupleObject *)(seq))))->ob_size)); |
1096 | PyObject **objects = PySequence_Fast_ITEMS(seq)(((((((PyObject*)(seq))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? ((PyListObject *)(seq))->ob_item : ((PyTupleObject *)(seq))->ob_item); |
1097 | |
1098 | if (update_shape(curr_dims, &max_dims, |
1099 | out_shape, 1, &size, NPY_TRUE1, flags) < 0) { |
1100 | /* But do update, if there this is a ragged case */ |
1101 | *flags |= FOUND_RAGGED_ARRAY; |
1102 | return max_dims; |
1103 | } |
1104 | if (size == 0) { |
1105 | /* If the sequence is empty, this must be the last dimension */ |
1106 | *flags |= MAX_DIMS_WAS_REACHED; |
1107 | return curr_dims + 1; |
1108 | } |
1109 | |
1110 | /* Allow keyboard interrupts. See gh issue 18117. */ |
1111 | if (PyErr_CheckSignals() < 0) { |
1112 | return -1; |
1113 | } |
1114 | |
1115 | /* Recursive call for each sequence item */ |
1116 | for (Py_ssize_t i = 0; i < size; i++) { |
1117 | max_dims = PyArray_DiscoverDTypeAndShape_Recursive( |
1118 | objects[i], curr_dims + 1, max_dims, |
1119 | out_descr, out_shape, coercion_cache_tail_ptr, fixed_DType, |
1120 | flags); |
1121 | |
1122 | if (max_dims < 0) { |
1123 | return -1; |
1124 | } |
1125 | } |
1126 | return max_dims; |
1127 | } |
1128 | |
1129 | |
1130 | /** |
1131 | * Finds the DType and shape of an arbitrary nested sequence. This is the |
1132 | * general purpose function to find the parameters of the array (but not |
1133 | * the array itself) as returned by `np.array()` |
1134 | * |
1135 | * Note: Before considering to make part of this public, we should consider |
1136 | * whether things such as `out_descr != NULL` should be supported in |
1137 | * a public API. |
1138 | * |
1139 | * @param obj Scalar or nested sequences. |
1140 | * @param max_dims Maximum number of dimensions (after this scalars are forced) |
1141 | * @param out_shape Will be filled with the output shape (more than the actual |
1142 | * shape may be written). |
1143 | * @param coercion_cache NULL initialized reference to a cache pointer. |
1144 | * May be set to the first coercion_cache, and has to be freed using |
1145 | * npy_free_coercion_cache. |
1146 | * This should be stored in a thread-safe manner (i.e. function static) |
1147 | * and is designed to be consumed by `PyArray_AssignFromCache`. |
1148 | * If not consumed, must be freed using `npy_free_coercion_cache`. |
1149 | * @param fixed_DType A user provided fixed DType class. |
1150 | * @param requested_descr A user provided fixed descriptor. This is always |
1151 | * returned as the discovered descriptor, but currently only used |
1152 | * for the ``__array__`` protocol. |
1153 | * @param out_descr Set to the discovered output descriptor. This may be |
1154 | * non NULL but only when fixed_DType/requested_descr are not given. |
1155 | * If non NULL, it is the first dtype being promoted and used if there |
1156 | * are no elements. |
1157 | * The result may be unchanged (remain NULL) when converting a |
1158 | * sequence with no elements. In this case it is callers responsibility |
1159 | * to choose a default. |
1160 | * @return dimensions of the discovered object or -1 on error. |
1161 | * WARNING: If (and only if) the output is a single array, the ndim |
1162 | * returned _can_ exceed the maximum allowed number of dimensions. |
1163 | * It might be nice to deprecate this? But it allows things such as |
1164 | * `arr1d[...] = np.array([[1,2,3,4]])` |
1165 | */ |
1166 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int |
1167 | PyArray_DiscoverDTypeAndShape( |
1168 | PyObject *obj, int max_dims, |
1169 | npy_intp out_shape[NPY_MAXDIMS32], |
1170 | coercion_cache_obj **coercion_cache, |
1171 | PyArray_DTypeMeta *fixed_DType, PyArray_Descr *requested_descr, |
1172 | PyArray_Descr **out_descr) |
1173 | { |
1174 | coercion_cache_obj **coercion_cache_head = coercion_cache; |
1175 | *coercion_cache = NULL((void*)0); |
1176 | enum _dtype_discovery_flags flags = 0; |
1177 | |
1178 | /* |
1179 | * Support a passed in descriptor (but only if nothing was specified). |
1180 | */ |
1181 | assert(*out_descr == NULL || fixed_DType == NULL)((void) (0)); |
1182 | /* Validate input of requested descriptor and DType */ |
1183 | if (fixed_DType != NULL((void*)0)) { |
1184 | assert(PyObject_TypeCheck(((void) (0)) |
1185 | (PyObject *)fixed_DType, (PyTypeObject *)&PyArrayDTypeMeta_Type))((void) (0)); |
1186 | } |
1187 | |
1188 | if (requested_descr != NULL((void*)0)) { |
1189 | assert(fixed_DType == NPY_DTYPE(requested_descr))((void) (0)); |
1190 | /* The output descriptor must be the input. */ |
1191 | Py_INCREF(requested_descr)_Py_INCREF(((PyObject*)(requested_descr))); |
1192 | *out_descr = requested_descr; |
1193 | flags |= DESCRIPTOR_WAS_SET; |
1194 | } |
1195 | |
1196 | /* |
1197 | * Call the recursive function, the setup for this may need expanding |
1198 | * to handle caching better. |
1199 | */ |
1200 | |
1201 | /* Legacy discovery flags */ |
1202 | if (requested_descr != NULL((void*)0)) { |
1203 | if (requested_descr->type_num == NPY_STRING && |
1204 | requested_descr->type == 'c') { |
1205 | /* Character dtype variation of string (should be deprecated...) */ |
1206 | flags |= DISCOVER_STRINGS_AS_SEQUENCES; |
1207 | } |
1208 | else if (requested_descr->type_num == NPY_VOID && |
1209 | (requested_descr->names || requested_descr->subarray)) { |
1210 | /* Void is a chimera, in that it may or may not be structured... */ |
1211 | flags |= DISCOVER_TUPLES_AS_ELEMENTS; |
1212 | } |
1213 | } |
1214 | |
1215 | int ndim = PyArray_DiscoverDTypeAndShape_Recursive( |
1216 | obj, 0, max_dims, out_descr, out_shape, &coercion_cache, |
1217 | fixed_DType, &flags); |
1218 | if (ndim < 0) { |
1219 | goto fail; |
1220 | } |
1221 | |
1222 | if (NPY_UNLIKELY(flags & FOUND_RAGGED_ARRAY)__builtin_expect(!!(flags & FOUND_RAGGED_ARRAY), 0)) { |
1223 | /* |
1224 | * If max-dims was reached and the dimensions reduced, this is ragged. |
1225 | * Otherwise, we merely reached the maximum dimensions, which is |
1226 | * slightly different. This happens for example for `[1, [2, 3]]` |
1227 | * where the maximum dimensions is 1, but then a sequence found. |
1228 | * |
1229 | * In this case we need to inform the user and clean out the cache |
1230 | * since it may be too deep. |
1231 | */ |
1232 | |
1233 | /* Handle reaching the maximum depth differently: */ |
1234 | int too_deep = ndim == max_dims; |
1235 | |
1236 | if (fixed_DType == NULL((void*)0)) { |
1237 | /* This is discovered as object, but deprecated */ |
1238 | static PyObject *visibleDeprecationWarning = NULL((void*)0); |
1239 | npy_cache_import( |
1240 | "numpy", "VisibleDeprecationWarning", |
1241 | &visibleDeprecationWarning); |
1242 | if (visibleDeprecationWarning == NULL((void*)0)) { |
1243 | goto fail; |
1244 | } |
1245 | if (!too_deep) { |
1246 | /* NumPy 1.19, 2019-11-01 */ |
1247 | if (PyErr_WarnEx(visibleDeprecationWarning, |
1248 | "Creating an ndarray from ragged nested sequences (which " |
1249 | "is a list-or-tuple of lists-or-tuples-or ndarrays with " |
1250 | "different lengths or shapes) is deprecated. If you " |
1251 | "meant to do this, you must specify 'dtype=object' " |
1252 | "when creating the ndarray.", 1) < 0) { |
1253 | goto fail; |
1254 | } |
1255 | } |
1256 | else { |
1257 | /* NumPy 1.20, 2020-05-08 */ |
1258 | /* Note, max_dims should normally always be NPY_MAXDIMS here */ |
1259 | if (PyErr_WarnFormat(visibleDeprecationWarning, 1, |
1260 | "Creating an ndarray from nested sequences exceeding " |
1261 | "the maximum number of dimensions of %d is deprecated. " |
1262 | "If you mean to do this, you must specify " |
1263 | "'dtype=object' when creating the ndarray.", |
1264 | max_dims) < 0) { |
1265 | goto fail; |
1266 | } |
1267 | } |
1268 | /* Ensure that ragged arrays always return object dtype */ |
1269 | Py_XSETREF(*out_descr, PyArray_DescrFromType(NPY_OBJECT))do { PyObject *_py_tmp = ((PyObject*)(*out_descr)); (*out_descr ) = (PyArray_DescrFromType(NPY_OBJECT)); _Py_XDECREF(((PyObject *)(_py_tmp))); } while (0); |
1270 | } |
1271 | else if (fixed_DType->type_num != NPY_OBJECT) { |
1272 | /* Only object DType supports ragged cases unify error */ |
1273 | |
1274 | /* |
1275 | * We used to let certain ragged arrays pass if they also |
1276 | * support e.g. conversion using `float(arr)`, which currently |
1277 | * works for arrays with only one element. |
1278 | * Thus we catch at least most of such cases here and give a |
1279 | * DeprecationWarning instead of an error. |
1280 | * Note that some of these will actually error later on when |
1281 | * attempting to do the actual assign. |
1282 | */ |
1283 | int deprecate_single_element_ragged = 0; |
1284 | coercion_cache_obj *current = *coercion_cache_head; |
1285 | while (current != NULL((void*)0)) { |
1286 | if (current->sequence) { |
1287 | if (current->depth == ndim) { |
1288 | /* |
1289 | * Assume that only array-likes will allow the deprecated |
1290 | * behaviour |
1291 | */ |
1292 | deprecate_single_element_ragged = 0; |
1293 | break; |
1294 | } |
1295 | /* check next converted sequence/array-like */ |
1296 | current = current->next; |
1297 | continue; |
1298 | } |
1299 | PyArrayObject *arr = (PyArrayObject *)(current->arr_or_sequence); |
1300 | assert(PyArray_NDIM(arr) + current->depth >= ndim)((void) (0)); |
1301 | if (PyArray_NDIM(arr) != ndim - current->depth) { |
1302 | /* This array is not compatible with the final shape */ |
1303 | if (PyArray_SIZE(arr)PyArray_MultiplyList(PyArray_DIMS(arr), PyArray_NDIM(arr)) != 1) { |
1304 | deprecate_single_element_ragged = 0; |
1305 | break; |
1306 | } |
1307 | deprecate_single_element_ragged = 1; |
1308 | } |
1309 | current = current->next; |
1310 | } |
1311 | |
1312 | if (deprecate_single_element_ragged) { |
1313 | /* Deprecated 2020-07-24, NumPy 1.20 */ |
1314 | if (DEPRECATE(PyErr_WarnEx(PyExc_DeprecationWarning,"setting an array element with a sequence. " "This was supported in some cases where the elements " "are arrays with a single element. For example " "`np.array([1, np.array([2])], dtype=int)`. " "In the future this will raise the same ValueError as " "`np.array([1, [2]], dtype=int)`.",1) |
1315 | "setting an array element with a sequence. "PyErr_WarnEx(PyExc_DeprecationWarning,"setting an array element with a sequence. " "This was supported in some cases where the elements " "are arrays with a single element. For example " "`np.array([1, np.array([2])], dtype=int)`. " "In the future this will raise the same ValueError as " "`np.array([1, [2]], dtype=int)`.",1) |
1316 | "This was supported in some cases where the elements "PyErr_WarnEx(PyExc_DeprecationWarning,"setting an array element with a sequence. " "This was supported in some cases where the elements " "are arrays with a single element. For example " "`np.array([1, np.array([2])], dtype=int)`. " "In the future this will raise the same ValueError as " "`np.array([1, [2]], dtype=int)`.",1) |
1317 | "are arrays with a single element. For example "PyErr_WarnEx(PyExc_DeprecationWarning,"setting an array element with a sequence. " "This was supported in some cases where the elements " "are arrays with a single element. For example " "`np.array([1, np.array([2])], dtype=int)`. " "In the future this will raise the same ValueError as " "`np.array([1, [2]], dtype=int)`.",1) |
1318 | "`np.array([1, np.array([2])], dtype=int)`. "PyErr_WarnEx(PyExc_DeprecationWarning,"setting an array element with a sequence. " "This was supported in some cases where the elements " "are arrays with a single element. For example " "`np.array([1, np.array([2])], dtype=int)`. " "In the future this will raise the same ValueError as " "`np.array([1, [2]], dtype=int)`.",1) |
1319 | "In the future this will raise the same ValueError as "PyErr_WarnEx(PyExc_DeprecationWarning,"setting an array element with a sequence. " "This was supported in some cases where the elements " "are arrays with a single element. For example " "`np.array([1, np.array([2])], dtype=int)`. " "In the future this will raise the same ValueError as " "`np.array([1, [2]], dtype=int)`.",1) |
1320 | "`np.array([1, [2]], dtype=int)`.")PyErr_WarnEx(PyExc_DeprecationWarning,"setting an array element with a sequence. " "This was supported in some cases where the elements " "are arrays with a single element. For example " "`np.array([1, np.array([2])], dtype=int)`. " "In the future this will raise the same ValueError as " "`np.array([1, [2]], dtype=int)`.",1) < 0) { |
1321 | goto fail; |
1322 | } |
1323 | } |
1324 | else if (!too_deep) { |
1325 | PyObject *shape = PyArray_IntTupleFromIntp(ndim, out_shape); |
1326 | PyErr_Format(PyExc_ValueError, |
1327 | "setting an array element with a sequence. The " |
1328 | "requested array has an inhomogeneous shape after " |
1329 | "%d dimensions. The detected shape was " |
1330 | "%R + inhomogeneous part.", |
1331 | ndim, shape); |
1332 | Py_DECREF(shape)_Py_DECREF(((PyObject*)(shape))); |
1333 | goto fail; |
1334 | } |
1335 | else { |
1336 | PyErr_Format(PyExc_ValueError, |
1337 | "setting an array element with a sequence. The " |
1338 | "requested array would exceed the maximum number of " |
1339 | "dimension of %d.", |
1340 | max_dims); |
1341 | goto fail; |
1342 | } |
1343 | } |
1344 | |
1345 | /* |
1346 | * If the array is ragged, the cache may be too deep, so clean it. |
1347 | * The cache is left at the same depth as the array though. |
1348 | */ |
1349 | coercion_cache_obj **next_ptr = coercion_cache_head; |
1350 | coercion_cache_obj *current = *coercion_cache_head; /* item to check */ |
1351 | while (current != NULL((void*)0)) { |
1352 | if (current->depth > ndim) { |
1353 | /* delete "next" cache item and advanced it (unlike later) */ |
1354 | current = npy_unlink_coercion_cache(current); |
1355 | continue; |
1356 | } |
1357 | /* advance both prev and next, and set prev->next to new item */ |
1358 | *next_ptr = current; |
1359 | next_ptr = &(current->next); |
1360 | current = current->next; |
1361 | } |
1362 | *next_ptr = NULL((void*)0); |
1363 | } |
1364 | /* We could check here for max-ndims being reached as well */ |
1365 | |
1366 | if (requested_descr != NULL((void*)0)) { |
1367 | /* descriptor was provided, we did not accidentally change it */ |
1368 | assert(*out_descr == requested_descr)((void) (0)); |
1369 | } |
1370 | else if (NPY_UNLIKELY(*out_descr == NULL)__builtin_expect(!!(*out_descr == ((void*)0)), 0)) { |
1371 | /* |
1372 | * When the object contained no elements (sequence of length zero), |
1373 | * the no descriptor may have been found. When a DType was requested |
1374 | * we use it to define the output dtype. |
1375 | * Otherwise, out_descr will remain NULL and the caller has to set |
1376 | * the correct default. |
1377 | */ |
1378 | if (fixed_DType != NULL((void*)0)) { |
1379 | *out_descr = fixed_DType->default_descr(fixed_DType); |
1380 | if (*out_descr == NULL((void*)0)) { |
1381 | goto fail; |
1382 | } |
1383 | } |
1384 | } |
1385 | return ndim; |
1386 | |
1387 | fail: |
1388 | npy_free_coercion_cache(*coercion_cache_head); |
1389 | *coercion_cache_head = NULL((void*)0); |
1390 | Py_XSETREF(*out_descr, NULL)do { PyObject *_py_tmp = ((PyObject*)(*out_descr)); (*out_descr ) = (((void*)0)); _Py_XDECREF(((PyObject*)(_py_tmp))); } while (0); |
1391 | return -1; |
1392 | } |
1393 | |
1394 | |
1395 | |
1396 | /** |
1397 | * Check the descriptor is a legacy "flexible" DType instance, this is |
1398 | * an instance which is (normally) not attached to an array, such as a string |
1399 | * of length 0 or a datetime with no unit. |
1400 | * These should be largely deprecated, and represent only the DType class |
1401 | * for most `dtype` parameters. |
1402 | * |
1403 | * TODO: This function should eventually recieve a deprecation warning and |
1404 | * be removed. |
1405 | * |
1406 | * @param descr |
1407 | * @return 1 if this is not a concrete dtype instance 0 otherwise |
1408 | */ |
1409 | static int |
1410 | descr_is_legacy_parametric_instance(PyArray_Descr *descr) |
1411 | { |
1412 | if (PyDataType_ISUNSIZED(descr)((descr)->elsize == 0 && !(((PyArray_Descr *)(descr ))->names != ((void*)0)))) { |
1413 | return 1; |
1414 | } |
1415 | /* Flexible descr with generic time unit (which can be adapted) */ |
1416 | if (PyDataType_ISDATETIME(descr)(((((PyArray_Descr*)(descr))->type_num) >=NPY_DATETIME) && ((((PyArray_Descr*)(descr))->type_num) <=NPY_TIMEDELTA ))) { |
1417 | PyArray_DatetimeMetaData *meta; |
1418 | meta = get_datetime_metadata_from_dtype(descr); |
1419 | if (meta->base == NPY_FR_GENERIC) { |
1420 | return 1; |
1421 | } |
1422 | } |
1423 | return 0; |
1424 | } |
1425 | |
1426 | |
1427 | /** |
1428 | * Given either a DType instance or class, (or legacy flexible instance), |
1429 | * ands sets output dtype instance and DType class. Both results may be |
1430 | * NULL, but if `out_descr` is set `out_DType` will always be the |
1431 | * corresponding class. |
1432 | * |
1433 | * @param dtype |
1434 | * @param out_descr |
1435 | * @param out_DType |
1436 | * @return 0 on success -1 on failure |
1437 | */ |
1438 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int |
1439 | PyArray_ExtractDTypeAndDescriptor(PyObject *dtype, |
1440 | PyArray_Descr **out_descr, PyArray_DTypeMeta **out_DType) |
1441 | { |
1442 | *out_DType = NULL((void*)0); |
1443 | *out_descr = NULL((void*)0); |
1444 | |
1445 | if (dtype != NULL((void*)0)) { |
1446 | if (PyObject_TypeCheck(dtype, (PyTypeObject *)&PyArrayDTypeMeta_Type)((((PyObject*)(dtype))->ob_type) == ((PyTypeObject *)& PyArrayDTypeMeta_Type) || PyType_IsSubtype((((PyObject*)(dtype ))->ob_type), ((PyTypeObject *)&PyArrayDTypeMeta_Type) ))) { |
1447 | assert(dtype != (PyObject * )&PyArrayDescr_Type)((void) (0)); /* not np.dtype */ |
1448 | *out_DType = (PyArray_DTypeMeta *)dtype; |
1449 | Py_INCREF(*out_DType)_Py_INCREF(((PyObject*)(*out_DType))); |
1450 | } |
1451 | else if (PyObject_TypeCheck((PyObject *)Py_TYPE(dtype),((((PyObject*)((PyObject *)(((PyObject*)(dtype))->ob_type) ))->ob_type) == ((PyTypeObject *)&PyArrayDTypeMeta_Type ) || PyType_IsSubtype((((PyObject*)((PyObject *)(((PyObject*) (dtype))->ob_type)))->ob_type), ((PyTypeObject *)&PyArrayDTypeMeta_Type ))) |
1452 | (PyTypeObject *)&PyArrayDTypeMeta_Type)((((PyObject*)((PyObject *)(((PyObject*)(dtype))->ob_type) ))->ob_type) == ((PyTypeObject *)&PyArrayDTypeMeta_Type ) || PyType_IsSubtype((((PyObject*)((PyObject *)(((PyObject*) (dtype))->ob_type)))->ob_type), ((PyTypeObject *)&PyArrayDTypeMeta_Type )))) { |
1453 | *out_DType = NPY_DTYPE(dtype); |
1454 | Py_INCREF(*out_DType)_Py_INCREF(((PyObject*)(*out_DType))); |
1455 | if (!descr_is_legacy_parametric_instance((PyArray_Descr *)dtype)) { |
1456 | *out_descr = (PyArray_Descr *)dtype; |
1457 | Py_INCREF(*out_descr)_Py_INCREF(((PyObject*)(*out_descr))); |
1458 | } |
1459 | } |
1460 | else { |
1461 | PyErr_SetString(PyExc_TypeError, |
1462 | "dtype parameter must be a DType instance or class."); |
1463 | return -1; |
1464 | } |
1465 | } |
1466 | return 0; |
1467 | } |
1468 | |
1469 | |
1470 | /* |
1471 | * Python API function to expose the dtype+shape discovery functionality |
1472 | * directly. |
1473 | */ |
1474 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * |
1475 | _discover_array_parameters(PyObject *NPY_UNUSED(self)(__NPY_UNUSED_TAGGEDself) __attribute__ ((__unused__)), |
1476 | PyObject *args, PyObject *kwargs) |
1477 | { |
1478 | static char *kwlist[] = {"obj", "dtype", NULL((void*)0)}; |
1479 | |
1480 | PyObject *obj; |
1481 | PyObject *dtype = NULL((void*)0); |
1482 | PyArray_Descr *fixed_descriptor = NULL((void*)0); |
1483 | PyArray_DTypeMeta *fixed_DType = NULL((void*)0); |
1484 | npy_intp shape[NPY_MAXDIMS32]; |
1485 | |
1486 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT( |
1487 | args, kwargs, "O|O:_discover_array_parameters", kwlist, |
1488 | &obj, &dtype)) { |
1489 | return NULL((void*)0); |
1490 | } |
1491 | |
1492 | if (PyArray_ExtractDTypeAndDescriptor(dtype, |
1493 | &fixed_descriptor, &fixed_DType) < 0) { |
1494 | return NULL((void*)0); |
1495 | } |
1496 | |
1497 | coercion_cache_obj *coercion_cache = NULL((void*)0); |
1498 | PyObject *out_dtype = NULL((void*)0); |
1499 | int ndim = PyArray_DiscoverDTypeAndShape( |
1500 | obj, NPY_MAXDIMS32, shape, |
1501 | &coercion_cache, |
1502 | fixed_DType, fixed_descriptor, (PyArray_Descr **)&out_dtype); |
1503 | Py_XDECREF(fixed_DType)_Py_XDECREF(((PyObject*)(fixed_DType))); |
1504 | Py_XDECREF(fixed_descriptor)_Py_XDECREF(((PyObject*)(fixed_descriptor))); |
1505 | if (ndim < 0) { |
1506 | return NULL((void*)0); |
1507 | } |
1508 | npy_free_coercion_cache(coercion_cache); |
1509 | if (out_dtype == NULL((void*)0)) { |
1510 | /* Empty sequence, report this as None. */ |
1511 | out_dtype = Py_None(&_Py_NoneStruct); |
1512 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); |
1513 | } |
1514 | |
1515 | PyObject *shape_tuple = PyArray_IntTupleFromIntp(ndim, shape); |
1516 | if (shape_tuple == NULL((void*)0)) { |
1517 | return NULL((void*)0); |
1518 | } |
1519 | |
1520 | PyObject *res = PyTuple_Pack(2, (PyObject *)out_dtype, shape_tuple); |
1521 | Py_DECREF(out_dtype)_Py_DECREF(((PyObject*)(out_dtype))); |
1522 | Py_DECREF(shape_tuple)_Py_DECREF(((PyObject*)(shape_tuple))); |
1523 | return res; |
1524 | } |
1 | void _Py_XDECREF(PyObject *op) { if (op
| ||||||||