Bug Summary

File:numpy/core/src/multiarray/ctors.c
Warning:line 1681, column 13
Accessing a PyObject whose ownership has been released

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name mapping.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-output=html -analyzer-checker=python -analyzer-disable-checker=deadcode -analyzer-config prune-paths=true,suppress-c++-stdlib=true,suppress-null-return-paths=false,crosscheck-with-z3=true,model-path=/opt/pyrefcon/lib/pyrefcon/models/models -analyzer-config experimental-enable-naive-ctu-analysis=true,ctu-dir=/tmp/pyrefcon/numpy/csa-scan,ctu-index-name=/tmp/pyrefcon/numpy/csa-scan/externalDefMap.txt,ctu-invocation-list=/tmp/pyrefcon/numpy/csa-scan/invocations.yaml,display-ctu-progress=false -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +sse -target-feature +sse2 -target-feature +sse3 -tune-cpu generic -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -fcoverage-compilation-dir=/tmp/pyrefcon/numpy -resource-dir /opt/pyrefcon/lib/clang/13.0.0 -isystem /opt/pyrefcon/lib/pyrefcon/models/python3.8 -D NDEBUG -D _FORTIFY_SOURCE=2 -D NPY_INTERNAL_BUILD=1 -D HAVE_NPY_CONFIG_H=1 -D _FILE_OFFSET_BITS=64 -D _LARGEFILE_SOURCE=1 -D _LARGEFILE64_SOURCE=1 -I build/src.linux-x86_64-3.8/numpy/core/src/common -I build/src.linux-x86_64-3.8/numpy/core/src/umath -I numpy/core/include -I build/src.linux-x86_64-3.8/numpy/core/include/numpy -I build/src.linux-x86_64-3.8/numpy/distutils/include -I numpy/core/src/common -I numpy/core/src -I numpy/core -I numpy/core/src/npymath -I numpy/core/src/multiarray -I numpy/core/src/umath -I numpy/core/src/npysort -I numpy/core/src/_simd -I build/src.linux-x86_64-3.8/numpy/core/src/common -I build/src.linux-x86_64-3.8/numpy/core/src/npymath -internal-isystem /opt/pyrefcon/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-result -Wsign-compare -Wall -Wformat -Werror=format-security -Wformat -Werror=format-security -Wdate-time -fdebug-compilation-dir=/tmp/pyrefcon/numpy -ferror-limit 19 -fwrapv -pthread -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/pyrefcon/numpy/csa-scan/reports -x c numpy/core/src/multiarray/mapping.c

numpy/core/src/multiarray/mapping.c

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
45static int
46_nonzero_indices(PyObject *myBool, PyArrayObject **arrays);
47
48/******************************************************************************
49 *** IMPLEMENT MAPPING PROTOCOL ***
50 *****************************************************************************/
51
52NPY_NO_EXPORT__attribute__((visibility("hidden"))) Py_ssize_t
53array_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 */
70static 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 */
117NPY_NO_EXPORT__attribute__((visibility("hidden"))) void
118PyArray_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
155static NPY_INLINEinline void
156multi_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 */
171static NPY_INLINEinline npy_intp
172unpack_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 */
189static NPY_INLINEinline npy_intp
190unpack_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 */
228NPY_NO_EXPORT__attribute__((visibility("hidden"))) npy_intp
229unpack_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
351fail:
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 */
379NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
380prepare_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) {
1
Taking false branch
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) {
2
Loop condition is true. Entering loop body
419 if (curr_idx > NPY_MAXDIMS32 * 2) {
3
Taking false branch
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)) {
4
Assuming the condition is false
5
Taking false branch
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)) {
6
Assuming the condition is false
7
Taking false branch
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)) {
8
Assuming the condition is false
9
Taking false branch
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) {
10
Assuming the condition is false
11
Taking false branch
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)))
) {
12
Assuming the condition is false
13
Assuming the condition is false
14
Taking false branch
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)) {
15
Assuming the condition is true
16
Taking true branch
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
16.1
'index_ndim' is equal to 1
16.1
'index_ndim' is equal to 1
16.1
'index_ndim' is equal to 1
16.1
'index_ndim' is equal to 1
== 1) && allow_boolean) {
17
Assuming 'allow_boolean' is 0
18
Taking false branch
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) {
19
Assuming the condition is false
20
Taking false branch
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);
21
Calling '_nonzero_indices'
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 */
848NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
849index_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 */
891static int
892get_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 */
924static int
925get_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 */
1019NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArrayObject *
1020array_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 */
1175NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
1176array_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 */
1345NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
1346array_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 */
1379NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
1380array_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 */
1405NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
1406array_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 */
1418NPY_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 */
1521NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
1522array_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 */
1743NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
1744array_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 */
1799static int
1800array_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
2089NPY_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 */
2112static 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,
22
Calling 'PyArray_FromAny'
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 */
2202NPY_NO_EXPORT__attribute__((visibility("hidden"))) void
2203PyArray_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 */
2250NPY_NO_EXPORT__attribute__((visibility("hidden"))) void
2251PyArray_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 */
2347static int
2348mapiter_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
2457broadcast_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 */
2499NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
2500PyArray_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
2612indexing_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 */
2672NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2673PyArray_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 */
3259NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
3260PyArray_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 */
3350NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
3351PyArray_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
3367static void
3368arraymapiter_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 */
3399NPY_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};

/tmp/pyrefcon/numpy/numpy/core/src/multiarray/ctors.c

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 */
53typedef int (*next_element)(void **, void *, PyArray_Descr *, void *);
54typedef int (*skip_separator)(void **, const char *, void *);
55
56
57static npy_bool
58string_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
68static int
69fromstr_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
94static int
95fromfile_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 */
117static char *
118swab_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 */
171static int
172fromstr_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
215static int
216fromfile_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 */
272static 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
330NPY_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
364NPY_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
424NPY_NO_EXPORT__attribute__((visibility("hidden"))) void
425byte_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 */
432NPY_NO_EXPORT__attribute__((visibility("hidden"))) void
433copy_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 */
462NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
463PyArray_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 */
585NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
586PyArray_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
620static void
621raise_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
647fail:
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 */
660NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
661PyArray_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 */
915NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
916PyArray_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 */
930NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
931PyArray_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 */
959NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
960PyArray_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 */
1058NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
1059PyArray_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 */
1068NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
1069PyArray_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
1097NPY_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
1120NPY_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
1242fail:
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 */
1269NPY_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*/
1350NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
1351PyArray_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 */
1377static int
1378setArrayFromSequence(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 */
1526NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
1527PyArray_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
22.1
'context' is equal to NULL
22.1
'context' is equal to NULL
22.1
'context' is equal to NULL
22.1
'context' is equal to NULL
!= NULL((void*)0)) {
23
Taking false branch
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,
24
Calling 'PyArray_ExtractDTypeAndDescriptor'
32
Returning from 'PyArray_ExtractDTypeAndDescriptor'
33
Taking false branch
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)));
34
Calling '_Py_XDECREF'
37
Returning from '_Py_XDECREF'
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) {
38
Assuming 'ndim' is >= 0
39
Taking false branch
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)
) {
40
Taking false branch
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)) {
41
Assuming 'dtype' is not equal to NULL
42
Taking false branch
1628 dtype = PyArray_DescrFromType(NPY_DEFAULT_TYPENPY_DOUBLE);
1629 }
1630
1631 if (min_depth
42.1
'min_depth' is equal to 0
42.1
'min_depth' is equal to 0
42.1
'min_depth' is equal to 0
42.1
'min_depth' is equal to 0
!= 0 && ndim < 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
42.2
'max_depth' is equal to 0
42.2
'max_depth' is equal to 0
42.2
'max_depth' is equal to 0
42.2
'max_depth' is equal to 0
!= 0 && ndim > 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)) {
43
Assuming 'cache' is equal to NULL
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
43.1
'cache' is equal to NULL
43.1
'cache' is equal to NULL
43.1
'cache' is equal to NULL
43.1
'cache' is equal to NULL
== NULL((void*)0) && PyArray_IsScalar(op, Void)(((((PyObject*)(op))->ob_type) == (&PyVoidArrType_Type
) || PyType_IsSubtype((((PyObject*)(op))->ob_type), (&
PyVoidArrType_Type))))
&&
44
Assuming the condition is true
1660 !(((PyVoidScalarObject *)op)->flags & NPY_ARRAY_OWNDATA0x0004) &&
45
Assuming the condition is false
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
45.1
'cache' is equal to null
45.1
'cache' is equal to null
45.1
'cache' is equal to null
45.1
'cache' is equal to null
== 0 && newtype
45.2
'newtype' is not equal to NULL
45.2
'newtype' is not equal to NULL
45.2
'newtype' is not equal to NULL
45.2
'newtype' is not equal to NULL
!= NULL((void*)0) &&
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))))
) {
46
Accessing a PyObject whose ownership has been released
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 */
1820NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
1821PyArray_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 */
1856NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
1857PyArray_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 */
2007NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2008PyArray_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 */
2086NPY_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 */
2108static NPY_INLINEinline int
2109deprecated_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*/
2137NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2138PyArray_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 */
2418NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2419PyArray_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*/
2476NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArray_Descr *
2477PyArray_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*/
2505NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2506PyArray_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*/
2519NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2520PyArray_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 */
2538NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2539PyArray_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*/
2561NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2562PyArray_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 */
2574NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
2575PyArray_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 */
2757NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
2758PyArray_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 */
2769NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
2770PyArray_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 */
2780NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
2781PyArray_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 */
2792NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2793PyArray_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 */
2848NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2849PyArray_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 */
2886NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2887PyArray_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 */
2922static 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*/
2947NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
2948PyArray_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 */
3034static 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 */
3144NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
3145PyArray_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. */
3299static PyArrayObject *
3300array_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
3356static PyArrayObject *
3357array_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
3454fail:
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 */
3485NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
3486PyArray_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*/
3544NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
3545PyArray_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 */
3662NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
3663PyArray_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 */
3759NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
3760PyArray_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
3893NPY_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 */
3983NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArrayObject *
3984PyArray_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}

/tmp/pyrefcon/numpy/numpy/core/src/multiarray/array_coercion.c

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 */
84PyObject *_global_pytype_to_type_dict = NULL((void*)0);
85
86
87/* Enum to track or signal some things during dtype and shape discovery */
88enum _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 */
105static 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 */
145NPY_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 */
208static NPY_INLINEinline PyArray_DTypeMeta *
209npy_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 */
247static NPY_INLINEinline PyArray_DTypeMeta *
248discover_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 */
332static NPY_INLINEinline PyArray_Descr *
333find_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 */
396NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
397PyArray_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
483static int
484update_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
538static int _coercion_cache_num = 0;
539static coercion_cache_obj *_coercion_cache_cache[COERCION_CACHE_CACHE_SIZE];
540
541/*
542 * Steals a reference to the object.
543 */
544static NPY_INLINEinline int
545npy_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 */
577NPY_NO_EXPORT__attribute__((visibility("hidden"))) coercion_cache_obj *
578npy_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
592NPY_NO_EXPORT__attribute__((visibility("hidden"))) void
593npy_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 */
613static NPY_INLINEinline int
614handle_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 */
658static NPY_INLINEinline int
659handle_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 */
703static int
704find_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 */
815NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArray_Descr *
816PyArray_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 */
863NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
864PyArray_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 */
1166NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
1167PyArray_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 */
1409static int
1410descr_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 */
1438NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
1439PyArray_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)) {
25
Assuming 'dtype' is not equal to NULL
26
Taking true branch
1446 if (PyObject_TypeCheck(dtype, (PyTypeObject *)&PyArrayDTypeMeta_Type)((((PyObject*)(dtype))->ob_type) == ((PyTypeObject *)&
PyArrayDTypeMeta_Type) || PyType_IsSubtype((((PyObject*)(dtype
))->ob_type), ((PyTypeObject *)&PyArrayDTypeMeta_Type)
))
) {
27
Assuming the condition is false
28
Assuming the condition is false
29
Taking false branch
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
)))
30
Assuming the condition is true
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)) {
31
Taking false branch
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 */
1474NPY_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}

/opt/pyrefcon/lib/pyrefcon/models/models/_Py_XDECREF.model

1void _Py_XDECREF(PyObject *op) { if (op
34.1
'op' is non-null
34.1
'op' is non-null
34.1
'op' is non-null
34.1
'op' is non-null
) --op->ob_refcnt; }
35
Taking true branch
36
Setting reference count to -1