Bug Summary

File:numpy/core/src/multiarray/array_coercion.c
Warning:line 1075, column 11
PyObject ownership leak with reference count of 1

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 arrayobject.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/arrayobject.c

numpy/core/src/multiarray/arrayobject.c

1/*
2 Provide multidimensional arrays as a basic object type in python.
3
4 Based on Original Numeric implementation
5 Copyright (c) 1995, 1996, 1997 Jim Hugunin, hugunin@mit.edu
6
7 with contributions from many Numeric Python developers 1995-2004
8
9 Heavily modified in 2005 with inspiration from Numarray
10
11 by
12
13 Travis Oliphant, oliphant@ee.byu.edu
14 Brigham Young University
15
16
17maintainer email: oliphant.travis@ieee.org
18
19 Numarray design (which provided guidance) by
20 Space Science Telescope Institute
21 (J. Todd Miller, Perry Greenfield, Rick White)
22*/
23#define PY_SSIZE_T_CLEAN
24#include <Python.h>
25#include "structmember.h"
26
27/*#include <stdio.h>*/
28#define NPY_NO_DEPRECATED_API0x0000000E NPY_API_VERSION0x0000000E
29#define _MULTIARRAYMODULE
30#include "numpy/arrayobject.h"
31#include "numpy/arrayscalars.h"
32
33#include "npy_config.h"
34
35#include "npy_pycompat.h"
36
37#include "common.h"
38
39#include "number.h"
40#include "usertypes.h"
41#include "arraytypes.h"
42#include "scalartypes.h"
43#include "arrayobject.h"
44#include "conversion_utils.h"
45#include "ctors.h"
46#include "dtypemeta.h"
47#include "methods.h"
48#include "descriptor.h"
49#include "iterators.h"
50#include "mapping.h"
51#include "getset.h"
52#include "sequence.h"
53#include "npy_buffer.h"
54#include "array_assign.h"
55#include "alloc.h"
56#include "mem_overlap.h"
57#include "numpyos.h"
58#include "strfuncs.h"
59
60#include "binop_override.h"
61#include "array_coercion.h"
62
63/*NUMPY_API
64 Compute the size of an array (in number of items)
65*/
66NPY_NO_EXPORT__attribute__((visibility("hidden"))) npy_intp
67PyArray_Size(PyObject *op)
68{
69 if (PyArray_Check(op)((((PyObject*)(op))->ob_type) == (&PyArray_Type) || PyType_IsSubtype
((((PyObject*)(op))->ob_type), (&PyArray_Type)))
) {
70 return PyArray_SIZE((PyArrayObject *)op)PyArray_MultiplyList(PyArray_DIMS((PyArrayObject *)op), PyArray_NDIM
((PyArrayObject *)op))
;
71 }
72 else {
73 return 0;
74 }
75}
76
77/*NUMPY_API
78 *
79 * Precondition: 'arr' is a copy of 'base' (though possibly with different
80 * strides, ordering, etc.). This function sets the UPDATEIFCOPY flag and the
81 * ->base pointer on 'arr', so that when 'arr' is destructed, it will copy any
82 * changes back to 'base'. DEPRECATED, use PyArray_SetWritebackIfCopyBase
83 *
84 * Steals a reference to 'base'.
85 *
86 * Returns 0 on success, -1 on failure.
87 */
88NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
89PyArray_SetUpdateIfCopyBase(PyArrayObject *arr, PyArrayObject *base)
90{
91 int ret;
92 /* 2017-Nov -10 1.14 (for PyPy only) */
93 /* 2018-April-21 1.15 (all Python implementations) */
94 if (DEPRECATE("PyArray_SetUpdateIfCopyBase is deprecated, use "PyErr_WarnEx(PyExc_DeprecationWarning,"PyArray_SetUpdateIfCopyBase is deprecated, use "
"PyArray_SetWritebackIfCopyBase instead, and be sure to call "
"PyArray_ResolveWritebackIfCopy before the array is deallocated, "
"i.e. before the last call to Py_DECREF. If cleaning up from an "
"error, PyArray_DiscardWritebackIfCopy may be called instead to "
"throw away the scratch buffer.",1)
95 "PyArray_SetWritebackIfCopyBase instead, and be sure to call "PyErr_WarnEx(PyExc_DeprecationWarning,"PyArray_SetUpdateIfCopyBase is deprecated, use "
"PyArray_SetWritebackIfCopyBase instead, and be sure to call "
"PyArray_ResolveWritebackIfCopy before the array is deallocated, "
"i.e. before the last call to Py_DECREF. If cleaning up from an "
"error, PyArray_DiscardWritebackIfCopy may be called instead to "
"throw away the scratch buffer.",1)
96 "PyArray_ResolveWritebackIfCopy before the array is deallocated, "PyErr_WarnEx(PyExc_DeprecationWarning,"PyArray_SetUpdateIfCopyBase is deprecated, use "
"PyArray_SetWritebackIfCopyBase instead, and be sure to call "
"PyArray_ResolveWritebackIfCopy before the array is deallocated, "
"i.e. before the last call to Py_DECREF. If cleaning up from an "
"error, PyArray_DiscardWritebackIfCopy may be called instead to "
"throw away the scratch buffer.",1)
97 "i.e. before the last call to Py_DECREF. If cleaning up from an "PyErr_WarnEx(PyExc_DeprecationWarning,"PyArray_SetUpdateIfCopyBase is deprecated, use "
"PyArray_SetWritebackIfCopyBase instead, and be sure to call "
"PyArray_ResolveWritebackIfCopy before the array is deallocated, "
"i.e. before the last call to Py_DECREF. If cleaning up from an "
"error, PyArray_DiscardWritebackIfCopy may be called instead to "
"throw away the scratch buffer.",1)
98 "error, PyArray_DiscardWritebackIfCopy may be called instead to "PyErr_WarnEx(PyExc_DeprecationWarning,"PyArray_SetUpdateIfCopyBase is deprecated, use "
"PyArray_SetWritebackIfCopyBase instead, and be sure to call "
"PyArray_ResolveWritebackIfCopy before the array is deallocated, "
"i.e. before the last call to Py_DECREF. If cleaning up from an "
"error, PyArray_DiscardWritebackIfCopy may be called instead to "
"throw away the scratch buffer.",1)
99 "throw away the scratch buffer.")PyErr_WarnEx(PyExc_DeprecationWarning,"PyArray_SetUpdateIfCopyBase is deprecated, use "
"PyArray_SetWritebackIfCopyBase instead, and be sure to call "
"PyArray_ResolveWritebackIfCopy before the array is deallocated, "
"i.e. before the last call to Py_DECREF. If cleaning up from an "
"error, PyArray_DiscardWritebackIfCopy may be called instead to "
"throw away the scratch buffer.",1)
< 0)
100 return -1;
101 ret = PyArray_SetWritebackIfCopyBase(arr, base);
102 if (ret >=0) {
103 PyArray_ENABLEFLAGS(arr, NPY_ARRAY_UPDATEIFCOPY0x1000);
104 PyArray_CLEARFLAGS(arr, NPY_ARRAY_WRITEBACKIFCOPY0x2000);
105 }
106 return ret;
107}
108
109/*NUMPY_API
110 *
111 * Precondition: 'arr' is a copy of 'base' (though possibly with different
112 * strides, ordering, etc.). This function sets the WRITEBACKIFCOPY flag and the
113 * ->base pointer on 'arr', call PyArray_ResolveWritebackIfCopy to copy any
114 * changes back to 'base' before deallocating the array.
115 *
116 * Steals a reference to 'base'.
117 *
118 * Returns 0 on success, -1 on failure.
119 */
120NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
121PyArray_SetWritebackIfCopyBase(PyArrayObject *arr, PyArrayObject *base)
122{
123 if (base == NULL((void*)0)) {
124 PyErr_SetString(PyExc_ValueError,
125 "Cannot WRITEBACKIFCOPY to NULL array");
126 return -1;
127 }
128 if (PyArray_BASE(arr) != NULL((void*)0)) {
129 PyErr_SetString(PyExc_ValueError,
130 "Cannot set array with existing base to WRITEBACKIFCOPY");
131 goto fail;
132 }
133 if (PyArray_FailUnlessWriteable(base, "WRITEBACKIFCOPY base") < 0) {
134 goto fail;
135 }
136
137 /*
138 * Any writes to 'arr' will magically turn into writes to 'base', so we
139 * should warn if necessary.
140 */
141 if (PyArray_FLAGS(base) & NPY_ARRAY_WARN_ON_WRITE) {
142 PyArray_ENABLEFLAGS(arr, NPY_ARRAY_WARN_ON_WRITE);
143 }
144
145 /*
146 * Unlike PyArray_SetBaseObject, we do not compress the chain of base
147 * references.
148 */
149 ((PyArrayObject_fields *)arr)->base = (PyObject *)base;
150 PyArray_ENABLEFLAGS(arr, NPY_ARRAY_WRITEBACKIFCOPY0x2000);
151 PyArray_CLEARFLAGS(base, NPY_ARRAY_WRITEABLE0x0400);
152
153 return 0;
154
155 fail:
156 Py_DECREF(base)_Py_DECREF(((PyObject*)(base)));
157 return -1;
158}
159
160/*NUMPY_API
161 * Sets the 'base' attribute of the array. This steals a reference
162 * to 'obj'.
163 *
164 * Returns 0 on success, -1 on failure.
165 */
166NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
167PyArray_SetBaseObject(PyArrayObject *arr, PyObject *obj)
168{
169 if (obj == NULL((void*)0)) {
170 PyErr_SetString(PyExc_ValueError,
171 "Cannot set the NumPy array 'base' "
172 "dependency to NULL after initialization");
173 return -1;
174 }
175 /*
176 * Allow the base to be set only once. Once the object which
177 * owns the data is set, it doesn't make sense to change it.
178 */
179 if (PyArray_BASE(arr) != NULL((void*)0)) {
180 Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj)));
181 PyErr_SetString(PyExc_ValueError,
182 "Cannot set the NumPy array 'base' "
183 "dependency more than once");
184 return -1;
185 }
186
187 /*
188 * Don't allow infinite chains of views, always set the base
189 * to the first owner of the data.
190 * That is, either the first object which isn't an array,
191 * or the first object which owns its own data.
192 */
193
194 while (PyArray_Check(obj)((((PyObject*)(obj))->ob_type) == (&PyArray_Type) || PyType_IsSubtype
((((PyObject*)(obj))->ob_type), (&PyArray_Type)))
&& (PyObject *)arr != obj) {
195 PyArrayObject *obj_arr = (PyArrayObject *)obj;
196 PyObject *tmp;
197
198 /* Propagate WARN_ON_WRITE through views. */
199 if (PyArray_FLAGS(obj_arr) & NPY_ARRAY_WARN_ON_WRITE) {
200 PyArray_ENABLEFLAGS(arr, NPY_ARRAY_WARN_ON_WRITE);
201 }
202
203 /* If this array owns its own data, stop collapsing */
204 if (PyArray_CHKFLAGS(obj_arr, NPY_ARRAY_OWNDATA0x0004)) {
205 break;
206 }
207
208 tmp = PyArray_BASE(obj_arr);
209 /* If there's no base, stop collapsing */
210 if (tmp == NULL((void*)0)) {
211 break;
212 }
213 /* Stop the collapse new base when the would not be of the same
214 * type (i.e. different subclass).
215 */
216 if (Py_TYPE(tmp)(((PyObject*)(tmp))->ob_type) != Py_TYPE(arr)(((PyObject*)(arr))->ob_type)) {
217 break;
218 }
219
220
221 Py_INCREF(tmp)_Py_INCREF(((PyObject*)(tmp)));
222 Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj)));
223 obj = tmp;
224 }
225
226 /* Disallow circular references */
227 if ((PyObject *)arr == obj) {
228 Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj)));
229 PyErr_SetString(PyExc_ValueError,
230 "Cannot create a circular NumPy array 'base' dependency");
231 return -1;
232 }
233
234 ((PyArrayObject_fields *)arr)->base = obj;
235
236 return 0;
237}
238
239
240/**
241 * Assign an arbitrary object a NumPy array. This is largely basically
242 * identical to PyArray_FromAny, but assigns directly to the output array.
243 *
244 * @param dest Array to be written to
245 * @param src_object Object to be assigned, array-coercion rules apply.
246 * @return 0 on success -1 on failures.
247 */
248/*NUMPY_API*/
249NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
250PyArray_CopyObject(PyArrayObject *dest, PyObject *src_object)
251{
252 int ret = 0;
253 PyArrayObject *view;
254 PyArray_Descr *dtype = NULL((void*)0);
255 int ndim;
256 npy_intp dims[NPY_MAXDIMS32];
257 coercion_cache_obj *cache = NULL((void*)0);
258
259 /*
260 * We have to set the maximum number of dimensions here to support
261 * sequences within object arrays.
262 */
263 ndim = PyArray_DiscoverDTypeAndShape(src_object,
1
Calling 'PyArray_DiscoverDTypeAndShape'
264 PyArray_NDIM(dest), dims, &cache,
265 NPY_DTYPE(PyArray_DESCR(dest))((PyArray_DTypeMeta *)(((PyObject*)(PyArray_DESCR(dest)))->
ob_type))
, PyArray_DESCR(dest), &dtype)
;
266 if (ndim < 0) {
267 return -1;
268 }
269
270 if (cache != NULL((void*)0) && !(cache->sequence)) {
271 /* The input is an array or array object, so assign directly */
272 assert(cache->converted_obj == src_object)((void) (0));
273 view = (PyArrayObject *)cache->arr_or_sequence;
274 Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype)));
275 ret = PyArray_AssignArray(dest, view, NULL((void*)0), NPY_UNSAFE_CASTING);
276 npy_free_coercion_cache(cache);
277 return ret;
278 }
279
280 /*
281 * We may need to broadcast, due to shape mismatches, in this case
282 * create a temporary array first, and assign that after filling
283 * it from the sequences/scalar.
284 */
285 if (ndim != PyArray_NDIM(dest) ||
286 !PyArray_CompareLists(PyArray_DIMS(dest), dims, ndim)) {
287 /*
288 * Broadcasting may be necessary, so assign to a view first.
289 * This branch could lead to a shape mismatch error later.
290 */
291 assert (ndim <= PyArray_NDIM(dest))((void) (0)); /* would error during discovery */
292 view = (PyArrayObject *) PyArray_NewFromDescr(
293 &PyArray_Type, dtype, ndim, dims, NULL((void*)0), NULL((void*)0),
294 PyArray_FLAGS(dest) & NPY_ARRAY_F_CONTIGUOUS0x0002, NULL((void*)0));
295 if (view == NULL((void*)0)) {
296 npy_free_coercion_cache(cache);
297 return -1;
298 }
299 }
300 else {
301 Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype)));
302 view = dest;
303 }
304
305 /* Assign the values to `view` (whichever array that is) */
306 if (cache == NULL((void*)0)) {
307 /* single (non-array) item, assign immediately */
308 if (PyArray_Pack(
309 PyArray_DESCR(view), PyArray_DATA(view), src_object) < 0) {
310 goto fail;
311 }
312 }
313 else {
314 if (PyArray_AssignFromCache(view, cache) < 0) {
315 goto fail;
316 }
317 }
318 if (view == dest) {
319 return 0;
320 }
321 ret = PyArray_AssignArray(dest, view, NULL((void*)0), NPY_UNSAFE_CASTING);
322 Py_DECREF(view)_Py_DECREF(((PyObject*)(view)));
323 return ret;
324
325 fail:
326 if (view != dest) {
327 Py_DECREF(view)_Py_DECREF(((PyObject*)(view)));
328 }
329 return -1;
330}
331
332
333/* returns an Array-Scalar Object of the type of arr
334 from the given pointer to memory -- main Scalar creation function
335 default new method calls this.
336*/
337
338/* Ideally, here the descriptor would contain all the information needed.
339 So, that we simply need the data and the descriptor, and perhaps
340 a flag
341*/
342
343
344/*
345 Given a string return the type-number for
346 the data-type with that string as the type-object name.
347 Returns NPY_NOTYPE without setting an error if no type can be
348 found. Only works for user-defined data-types.
349*/
350
351/*NUMPY_API
352 */
353NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
354PyArray_TypeNumFromName(char const *str)
355{
356 int i;
357 PyArray_Descr *descr;
358
359 for (i = 0; i < NPY_NUMUSERTYPES; i++) {
360 descr = userdescrs[i];
361 if (strcmp(descr->typeobj->tp_name, str) == 0) {
362 return descr->type_num;
363 }
364 }
365 return NPY_NOTYPE;
366}
367
368/*NUMPY_API
369 *
370 * If WRITEBACKIFCOPY and self has data, reset the base WRITEABLE flag,
371 * copy the local data to base, release the local data, and set flags
372 * appropriately. Return 0 if not relevant, 1 if success, < 0 on failure
373 */
374NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
375PyArray_ResolveWritebackIfCopy(PyArrayObject * self)
376{
377 PyArrayObject_fields *fa = (PyArrayObject_fields *)self;
378 if (fa && fa->base) {
379 if ((fa->flags & NPY_ARRAY_UPDATEIFCOPY0x1000) || (fa->flags & NPY_ARRAY_WRITEBACKIFCOPY0x2000)) {
380 /*
381 * UPDATEIFCOPY or WRITEBACKIFCOPY means that fa->base's data
382 * should be updated with the contents
383 * of self.
384 * fa->base->flags is not WRITEABLE to protect the relationship
385 * unlock it.
386 */
387 int retval = 0;
388 PyArray_ENABLEFLAGS(((PyArrayObject *)fa->base),
389 NPY_ARRAY_WRITEABLE0x0400);
390 PyArray_CLEARFLAGS(self, NPY_ARRAY_UPDATEIFCOPY0x1000);
391 PyArray_CLEARFLAGS(self, NPY_ARRAY_WRITEBACKIFCOPY0x2000);
392 retval = PyArray_CopyAnyInto((PyArrayObject *)fa->base, self);
393 Py_DECREF(fa->base)_Py_DECREF(((PyObject*)(fa->base)));
394 fa->base = NULL((void*)0);
395 if (retval < 0) {
396 /* this should never happen, how did the two copies of data
397 * get out of sync?
398 */
399 return retval;
400 }
401 return 1;
402 }
403 }
404 return 0;
405}
406
407/*********************** end C-API functions **********************/
408
409
410/* dealloc must not raise an error, best effort try to write
411 to stderr and clear the error
412*/
413
414static NPY_INLINEinline void
415WARN_IN_DEALLOC(PyObject* warning, const char * msg) {
416 if (PyErr_WarnEx(warning, msg, 1) < 0) {
417 PyObject * s;
418
419 s = PyUnicode_FromString("array_dealloc");
420 if (s) {
421 PyErr_WriteUnraisable(s);
422 Py_DECREF(s)_Py_DECREF(((PyObject*)(s)));
423 }
424 else {
425 PyErr_WriteUnraisable(Py_None(&_Py_NoneStruct));
426 }
427 }
428}
429
430/* array object functions */
431
432static void
433array_dealloc(PyArrayObject *self)
434{
435 PyArrayObject_fields *fa = (PyArrayObject_fields *)self;
436
437 if (_buffer_info_free(fa->_buffer_info, (PyObject *)self) < 0) {
438 PyErr_WriteUnraisable(NULL((void*)0));
439 }
440
441 if (fa->weakreflist != NULL((void*)0)) {
442 PyObject_ClearWeakRefs((PyObject *)self);
443 }
444 if (fa->base) {
445 int retval;
446 if (PyArray_FLAGS(self) & NPY_ARRAY_WRITEBACKIFCOPY0x2000)
447 {
448 char const * msg = "WRITEBACKIFCOPY detected in array_dealloc. "
449 " Required call to PyArray_ResolveWritebackIfCopy or "
450 "PyArray_DiscardWritebackIfCopy is missing.";
451 /*
452 * prevent reaching 0 twice and thus recursing into dealloc.
453 * Increasing sys.gettotalrefcount, but path should not be taken.
454 */
455 Py_INCREF(self)_Py_INCREF(((PyObject*)(self)));
456 WARN_IN_DEALLOC(PyExc_RuntimeWarning, msg);
457 retval = PyArray_ResolveWritebackIfCopy(self);
458 if (retval < 0)
459 {
460 PyErr_Print();
461 PyErr_Clear();
462 }
463 }
464 if (PyArray_FLAGS(self) & NPY_ARRAY_UPDATEIFCOPY0x1000) {
465 /* DEPRECATED, remove once the flag is removed */
466 char const * msg = "UPDATEIFCOPY detected in array_dealloc. "
467 " Required call to PyArray_ResolveWritebackIfCopy or "
468 "PyArray_DiscardWritebackIfCopy is missing";
469 /*
470 * prevent reaching 0 twice and thus recursing into dealloc.
471 * Increasing sys.gettotalrefcount, but path should not be taken.
472 */
473 Py_INCREF(self)_Py_INCREF(((PyObject*)(self)));
474 /* 2017-Nov-10 1.14 */
475 WARN_IN_DEALLOC(PyExc_DeprecationWarning, msg);
476 retval = PyArray_ResolveWritebackIfCopy(self);
477 if (retval < 0)
478 {
479 PyErr_Print();
480 PyErr_Clear();
481 }
482 }
483 /*
484 * If fa->base is non-NULL, it is something
485 * to DECREF -- either a view or a buffer object
486 */
487 Py_XDECREF(fa->base)_Py_XDECREF(((PyObject*)(fa->base)));
488 }
489
490 if ((fa->flags & NPY_ARRAY_OWNDATA0x0004) && fa->data) {
491 /* Free internal references if an Object array */
492 if (PyDataType_FLAGCHK(fa->descr, NPY_ITEM_REFCOUNT)(((fa->descr)->flags & (0x01)) == (0x01))) {
493 PyArray_XDECREF(self);
494 }
495 npy_free_cache(fa->data, PyArray_NBYTES(self)(PyArray_ITEMSIZE(self) * PyArray_MultiplyList(PyArray_DIMS(self
), PyArray_NDIM(self)))
);
496 }
497
498 /* must match allocation in PyArray_NewFromDescr */
499 npy_free_cache_dim(fa->dimensions, 2 * fa->nd);
500 Py_DECREF(fa->descr)_Py_DECREF(((PyObject*)(fa->descr)));
501 Py_TYPE(self)(((PyObject*)(self))->ob_type)->tp_free((PyObject *)self);
502}
503
504/*NUMPY_API
505 * Prints the raw data of the ndarray in a form useful for debugging
506 * low-level C issues.
507 */
508NPY_NO_EXPORT__attribute__((visibility("hidden"))) void
509PyArray_DebugPrint(PyArrayObject *obj)
510{
511 int i;
512 PyArrayObject_fields *fobj = (PyArrayObject_fields *)obj;
513
514 printf("-------------------------------------------------------\n")__printf_chk (2 - 1, "-------------------------------------------------------\n"
)
;
515 printf(" Dump of NumPy ndarray at address %p\n", obj)__printf_chk (2 - 1, " Dump of NumPy ndarray at address %p\n"
, obj)
;
516 if (obj == NULL((void*)0)) {
517 printf(" It's NULL!\n")__printf_chk (2 - 1, " It's NULL!\n");
518 printf("-------------------------------------------------------\n")__printf_chk (2 - 1, "-------------------------------------------------------\n"
)
;
519 fflush(stdoutstdout);
520 return;
521 }
522 printf(" ndim : %d\n", fobj->nd)__printf_chk (2 - 1, " ndim : %d\n", fobj->nd);
523 printf(" shape :")__printf_chk (2 - 1, " shape :");
524 for (i = 0; i < fobj->nd; ++i) {
525 printf(" %" NPY_INTP_FMT, fobj->dimensions[i])__printf_chk (2 - 1, " %" "ld", fobj->dimensions[i]);
526 }
527 printf("\n")__printf_chk (2 - 1, "\n");
528
529 printf(" dtype : ")__printf_chk (2 - 1, " dtype : ");
530 PyObject_Print((PyObject *)fobj->descr, stdoutstdout, 0);
531 printf("\n")__printf_chk (2 - 1, "\n");
532 printf(" data : %p\n", fobj->data)__printf_chk (2 - 1, " data : %p\n", fobj->data);
533 printf(" strides:")__printf_chk (2 - 1, " strides:");
534 for (i = 0; i < fobj->nd; ++i) {
535 printf(" %" NPY_INTP_FMT, fobj->strides[i])__printf_chk (2 - 1, " %" "ld", fobj->strides[i]);
536 }
537 printf("\n")__printf_chk (2 - 1, "\n");
538
539 printf(" base : %p\n", fobj->base)__printf_chk (2 - 1, " base : %p\n", fobj->base);
540
541 printf(" flags :")__printf_chk (2 - 1, " flags :");
542 if (fobj->flags & NPY_ARRAY_C_CONTIGUOUS0x0001)
543 printf(" NPY_C_CONTIGUOUS")__printf_chk (2 - 1, " NPY_C_CONTIGUOUS");
544 if (fobj->flags & NPY_ARRAY_F_CONTIGUOUS0x0002)
545 printf(" NPY_F_CONTIGUOUS")__printf_chk (2 - 1, " NPY_F_CONTIGUOUS");
546 if (fobj->flags & NPY_ARRAY_OWNDATA0x0004)
547 printf(" NPY_OWNDATA")__printf_chk (2 - 1, " NPY_OWNDATA");
548 if (fobj->flags & NPY_ARRAY_ALIGNED0x0100)
549 printf(" NPY_ALIGNED")__printf_chk (2 - 1, " NPY_ALIGNED");
550 if (fobj->flags & NPY_ARRAY_WRITEABLE0x0400)
551 printf(" NPY_WRITEABLE")__printf_chk (2 - 1, " NPY_WRITEABLE");
552 if (fobj->flags & NPY_ARRAY_UPDATEIFCOPY0x1000)
553 printf(" NPY_UPDATEIFCOPY")__printf_chk (2 - 1, " NPY_UPDATEIFCOPY");
554 if (fobj->flags & NPY_ARRAY_WRITEBACKIFCOPY0x2000)
555 printf(" NPY_WRITEBACKIFCOPY")__printf_chk (2 - 1, " NPY_WRITEBACKIFCOPY");
556 printf("\n")__printf_chk (2 - 1, "\n");
557
558 if (fobj->base != NULL((void*)0) && PyArray_Check(fobj->base)((((PyObject*)(fobj->base))->ob_type) == (&PyArray_Type
) || PyType_IsSubtype((((PyObject*)(fobj->base))->ob_type
), (&PyArray_Type)))
) {
559 printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n")__printf_chk (2 - 1, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"
)
;
560 printf("Dump of array's BASE:\n")__printf_chk (2 - 1, "Dump of array's BASE:\n");
561 PyArray_DebugPrint((PyArrayObject *)fobj->base);
562 printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n")__printf_chk (2 - 1, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
)
;
563 }
564 printf("-------------------------------------------------------\n")__printf_chk (2 - 1, "-------------------------------------------------------\n"
)
;
565 fflush(stdoutstdout);
566}
567
568
569/*NUMPY_API
570 * This function is scheduled to be removed
571 *
572 * TO BE REMOVED - NOT USED INTERNALLY.
573 */
574NPY_NO_EXPORT__attribute__((visibility("hidden"))) void
575PyArray_SetDatetimeParseFunction(PyObject *NPY_UNUSED(op)(__NPY_UNUSED_TAGGEDop) __attribute__ ((__unused__)))
576{
577}
578
579/*NUMPY_API
580 */
581NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
582PyArray_CompareUCS4(npy_ucs4 const *s1, npy_ucs4 const *s2, size_t len)
583{
584 npy_ucs4 c1, c2;
585 while(len-- > 0) {
586 c1 = *s1++;
587 c2 = *s2++;
588 if (c1 != c2) {
589 return (c1 < c2) ? -1 : 1;
590 }
591 }
592 return 0;
593}
594
595/*NUMPY_API
596 */
597NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
598PyArray_CompareString(const char *s1, const char *s2, size_t len)
599{
600 const unsigned char *c1 = (unsigned char *)s1;
601 const unsigned char *c2 = (unsigned char *)s2;
602 size_t i;
603
604 for(i = 0; i < len; ++i) {
605 if (c1[i] != c2[i]) {
606 return (c1[i] > c2[i]) ? 1 : -1;
607 }
608 }
609 return 0;
610}
611
612
613/* Call this from contexts where an array might be written to, but we have no
614 * way to tell. (E.g., when converting to a read-write buffer.)
615 */
616NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
617array_might_be_written(PyArrayObject *obj)
618{
619 const char *msg =
620 "Numpy has detected that you (may be) writing to an array with\n"
621 "overlapping memory from np.broadcast_arrays. If this is intentional\n"
622 "set the WRITEABLE flag True or make a copy immediately before writing.";
623 if (PyArray_FLAGS(obj) & NPY_ARRAY_WARN_ON_WRITE) {
624 if (DEPRECATE(msg)PyErr_WarnEx(PyExc_DeprecationWarning,msg,1) < 0) {
625 return -1;
626 }
627 /* Only warn once per array */
628 while (1) {
629 PyArray_CLEARFLAGS(obj, NPY_ARRAY_WARN_ON_WRITE);
630 if (!PyArray_BASE(obj) || !PyArray_Check(PyArray_BASE(obj))((((PyObject*)(PyArray_BASE(obj)))->ob_type) == (&PyArray_Type
) || PyType_IsSubtype((((PyObject*)(PyArray_BASE(obj)))->ob_type
), (&PyArray_Type)))
) {
631 break;
632 }
633 obj = (PyArrayObject *)PyArray_BASE(obj);
634 }
635 }
636 return 0;
637}
638
639/*NUMPY_API
640 *
641 * This function does nothing if obj is writeable, and raises an exception
642 * (and returns -1) if obj is not writeable. It may also do other
643 * house-keeping, such as issuing warnings on arrays which are transitioning
644 * to become views. Always call this function at some point before writing to
645 * an array.
646 *
647 * 'name' is a name for the array, used to give better error
648 * messages. Something like "assignment destination", "output array", or even
649 * just "array".
650 */
651NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
652PyArray_FailUnlessWriteable(PyArrayObject *obj, const char *name)
653{
654 if (!PyArray_ISWRITEABLE(obj)PyArray_CHKFLAGS((obj), 0x0400)) {
655 PyErr_Format(PyExc_ValueError, "%s is read-only", name);
656 return -1;
657 }
658 if (array_might_be_written(obj) < 0) {
659 return -1;
660 }
661 return 0;
662}
663
664/* This also handles possibly mis-aligned data */
665/* Compare s1 and s2 which are not necessarily NULL-terminated.
666 s1 is of length len1
667 s2 is of length len2
668 If they are NULL terminated, then stop comparison.
669*/
670static int
671_myunincmp(npy_ucs4 const *s1, npy_ucs4 const *s2, int len1, int len2)
672{
673 npy_ucs4 const *sptr;
674 npy_ucs4 *s1t = NULL((void*)0);
675 npy_ucs4 *s2t = NULL((void*)0);
676 int val;
677 npy_intp size;
678 int diff;
679
680 /* Replace `s1` and `s2` with aligned copies if needed */
681 if ((npy_intp)s1 % sizeof(npy_ucs4) != 0) {
682 size = len1*sizeof(npy_ucs4);
683 s1t = malloc(size);
684 memcpy(s1t, s1, size);
685 s1 = s1t;
686 }
687 if ((npy_intp)s2 % sizeof(npy_ucs4) != 0) {
688 size = len2*sizeof(npy_ucs4);
689 s2t = malloc(size);
690 memcpy(s2t, s2, size);
691 s2 = s1t;
692 }
693
694 val = PyArray_CompareUCS4(s1, s2, PyArray_MIN(len1,len2)(((len1)<(len2))?(len1):(len2)));
695 if ((val != 0) || (len1 == len2)) {
696 goto finish;
697 }
698 if (len2 > len1) {
699 sptr = s2+len1;
700 val = -1;
701 diff = len2-len1;
702 }
703 else {
704 sptr = s1+len2;
705 val = 1;
706 diff=len1-len2;
707 }
708 while (diff--) {
709 if (*sptr != 0) {
710 goto finish;
711 }
712 sptr++;
713 }
714 val = 0;
715
716 finish:
717 /* Cleanup the aligned copies */
718 if (s1t) {
719 free(s1t);
720 }
721 if (s2t) {
722 free(s2t);
723 }
724 return val;
725}
726
727
728
729
730/*
731 * Compare s1 and s2 which are not necessarily NULL-terminated.
732 * s1 is of length len1
733 * s2 is of length len2
734 * If they are NULL terminated, then stop comparison.
735 */
736static int
737_mystrncmp(char const *s1, char const *s2, int len1, int len2)
738{
739 char const *sptr;
740 int val;
741 int diff;
742
743 val = memcmp(s1, s2, PyArray_MIN(len1, len2)(((len1)<(len2))?(len1):(len2)));
744 if ((val != 0) || (len1 == len2)) {
745 return val;
746 }
747 if (len2 > len1) {
748 sptr = s2 + len1;
749 val = -1;
750 diff = len2 - len1;
751 }
752 else {
753 sptr = s1 + len2;
754 val = 1;
755 diff = len1 - len2;
756 }
757 while (diff--) {
758 if (*sptr != 0) {
759 return val;
760 }
761 sptr++;
762 }
763 return 0; /* Only happens if NULLs are everywhere */
764}
765
766/* Borrowed from Numarray */
767
768#define SMALL_STRING 2048
769
770static void _rstripw(char *s, int n)
771{
772 int i;
773 for (i = n - 1; i >= 1; i--) { /* Never strip to length 0. */
774 int c = s[i];
775
776 if (!c || NumPyOS_ascii_isspace((int)c)) {
777 s[i] = 0;
778 }
779 else {
780 break;
781 }
782 }
783}
784
785static void _unistripw(npy_ucs4 *s, int n)
786{
787 int i;
788 for (i = n - 1; i >= 1; i--) { /* Never strip to length 0. */
789 npy_ucs4 c = s[i];
790 if (!c || NumPyOS_ascii_isspace((int)c)) {
791 s[i] = 0;
792 }
793 else {
794 break;
795 }
796 }
797}
798
799
800static char *
801_char_copy_n_strip(char const *original, char *temp, int nc)
802{
803 if (nc > SMALL_STRING) {
804 temp = malloc(nc);
805 if (!temp) {
806 PyErr_NoMemory();
807 return NULL((void*)0);
808 }
809 }
810 memcpy(temp, original, nc);
811 _rstripw(temp, nc);
812 return temp;
813}
814
815static void
816_char_release(char *ptr, int nc)
817{
818 if (nc > SMALL_STRING) {
819 free(ptr);
820 }
821}
822
823static char *
824_uni_copy_n_strip(char const *original, char *temp, int nc)
825{
826 if (nc*sizeof(npy_ucs4) > SMALL_STRING) {
827 temp = malloc(nc*sizeof(npy_ucs4));
828 if (!temp) {
829 PyErr_NoMemory();
830 return NULL((void*)0);
831 }
832 }
833 memcpy(temp, original, nc*sizeof(npy_ucs4));
834 _unistripw((npy_ucs4 *)temp, nc);
835 return temp;
836}
837
838static void
839_uni_release(char *ptr, int nc)
840{
841 if (nc*sizeof(npy_ucs4) > SMALL_STRING) {
842 free(ptr);
843 }
844}
845
846
847/* End borrowed from numarray */
848
849#define _rstrip_loop(CMP) { \
850 void *aptr, *bptr; \
851 char atemp[SMALL_STRING], btemp[SMALL_STRING]; \
852 while(size--) { \
853 aptr = stripfunc(iself->dataptr, atemp, N1); \
854 if (!aptr) return -1; \
855 bptr = stripfunc(iother->dataptr, btemp, N2); \
856 if (!bptr) { \
857 relfunc(aptr, N1); \
858 return -1; \
859 } \
860 val = compfunc(aptr, bptr, N1, N2); \
861 *dptr = (val CMP 0); \
862 PyArray_ITER_NEXT(iself)do { ((PyArrayIterObject *)(iself))->index++; if (((PyArrayIterObject
*)(iself))->nd_m1 == 0) { do { (((PyArrayIterObject *)(iself
)))->dataptr += ((PyArrayIterObject *)(((PyArrayIterObject
*)(iself))))->strides[0]; (((PyArrayIterObject *)(iself))
)->coordinates[0]++; } while (0); } else if (((PyArrayIterObject
*)(iself))->contiguous) ((PyArrayIterObject *)(iself))->
dataptr += PyArray_DESCR(((PyArrayIterObject *)(iself))->ao
)->elsize; else if (((PyArrayIterObject *)(iself))->nd_m1
== 1) { do { if ((((PyArrayIterObject *)(iself)))->coordinates
[1] < (((PyArrayIterObject *)(iself)))->dims_m1[1]) { (
((PyArrayIterObject *)(iself)))->coordinates[1]++; (((PyArrayIterObject
*)(iself)))->dataptr += (((PyArrayIterObject *)(iself)))->
strides[1]; } else { (((PyArrayIterObject *)(iself)))->coordinates
[1] = 0; (((PyArrayIterObject *)(iself)))->coordinates[0]++
; (((PyArrayIterObject *)(iself)))->dataptr += (((PyArrayIterObject
*)(iself)))->strides[0] - (((PyArrayIterObject *)(iself))
)->backstrides[1]; } } while (0); } else { int __npy_i; for
(__npy_i=((PyArrayIterObject *)(iself))->nd_m1; __npy_i >=
0; __npy_i--) { if (((PyArrayIterObject *)(iself))->coordinates
[__npy_i] < ((PyArrayIterObject *)(iself))->dims_m1[__npy_i
]) { ((PyArrayIterObject *)(iself))->coordinates[__npy_i]++
; ((PyArrayIterObject *)(iself))->dataptr += ((PyArrayIterObject
*)(iself))->strides[__npy_i]; break; } else { ((PyArrayIterObject
*)(iself))->coordinates[__npy_i] = 0; ((PyArrayIterObject
*)(iself))->dataptr -= ((PyArrayIterObject *)(iself))->
backstrides[__npy_i]; } } } } while (0)
; \
863 PyArray_ITER_NEXT(iother)do { ((PyArrayIterObject *)(iother))->index++; if (((PyArrayIterObject
*)(iother))->nd_m1 == 0) { do { (((PyArrayIterObject *)(iother
)))->dataptr += ((PyArrayIterObject *)(((PyArrayIterObject
*)(iother))))->strides[0]; (((PyArrayIterObject *)(iother
)))->coordinates[0]++; } while (0); } else if (((PyArrayIterObject
*)(iother))->contiguous) ((PyArrayIterObject *)(iother))->
dataptr += PyArray_DESCR(((PyArrayIterObject *)(iother))->
ao)->elsize; else if (((PyArrayIterObject *)(iother))->
nd_m1 == 1) { do { if ((((PyArrayIterObject *)(iother)))->
coordinates[1] < (((PyArrayIterObject *)(iother)))->dims_m1
[1]) { (((PyArrayIterObject *)(iother)))->coordinates[1]++
; (((PyArrayIterObject *)(iother)))->dataptr += (((PyArrayIterObject
*)(iother)))->strides[1]; } else { (((PyArrayIterObject *
)(iother)))->coordinates[1] = 0; (((PyArrayIterObject *)(iother
)))->coordinates[0]++; (((PyArrayIterObject *)(iother)))->
dataptr += (((PyArrayIterObject *)(iother)))->strides[0] -
(((PyArrayIterObject *)(iother)))->backstrides[1]; } } while
(0); } else { int __npy_i; for (__npy_i=((PyArrayIterObject *
)(iother))->nd_m1; __npy_i >= 0; __npy_i--) { if (((PyArrayIterObject
*)(iother))->coordinates[__npy_i] < ((PyArrayIterObject
*)(iother))->dims_m1[__npy_i]) { ((PyArrayIterObject *)(iother
))->coordinates[__npy_i]++; ((PyArrayIterObject *)(iother)
)->dataptr += ((PyArrayIterObject *)(iother))->strides[
__npy_i]; break; } else { ((PyArrayIterObject *)(iother))->
coordinates[__npy_i] = 0; ((PyArrayIterObject *)(iother))->
dataptr -= ((PyArrayIterObject *)(iother))->backstrides[__npy_i
]; } } } } while (0)
; \
864 dptr += 1; \
865 relfunc(aptr, N1); \
866 relfunc(bptr, N2); \
867 } \
868 }
869
870#define _reg_loop(CMP) { \
871 while(size--) { \
872 val = compfunc((void *)iself->dataptr, \
873 (void *)iother->dataptr, \
874 N1, N2); \
875 *dptr = (val CMP 0); \
876 PyArray_ITER_NEXT(iself)do { ((PyArrayIterObject *)(iself))->index++; if (((PyArrayIterObject
*)(iself))->nd_m1 == 0) { do { (((PyArrayIterObject *)(iself
)))->dataptr += ((PyArrayIterObject *)(((PyArrayIterObject
*)(iself))))->strides[0]; (((PyArrayIterObject *)(iself))
)->coordinates[0]++; } while (0); } else if (((PyArrayIterObject
*)(iself))->contiguous) ((PyArrayIterObject *)(iself))->
dataptr += PyArray_DESCR(((PyArrayIterObject *)(iself))->ao
)->elsize; else if (((PyArrayIterObject *)(iself))->nd_m1
== 1) { do { if ((((PyArrayIterObject *)(iself)))->coordinates
[1] < (((PyArrayIterObject *)(iself)))->dims_m1[1]) { (
((PyArrayIterObject *)(iself)))->coordinates[1]++; (((PyArrayIterObject
*)(iself)))->dataptr += (((PyArrayIterObject *)(iself)))->
strides[1]; } else { (((PyArrayIterObject *)(iself)))->coordinates
[1] = 0; (((PyArrayIterObject *)(iself)))->coordinates[0]++
; (((PyArrayIterObject *)(iself)))->dataptr += (((PyArrayIterObject
*)(iself)))->strides[0] - (((PyArrayIterObject *)(iself))
)->backstrides[1]; } } while (0); } else { int __npy_i; for
(__npy_i=((PyArrayIterObject *)(iself))->nd_m1; __npy_i >=
0; __npy_i--) { if (((PyArrayIterObject *)(iself))->coordinates
[__npy_i] < ((PyArrayIterObject *)(iself))->dims_m1[__npy_i
]) { ((PyArrayIterObject *)(iself))->coordinates[__npy_i]++
; ((PyArrayIterObject *)(iself))->dataptr += ((PyArrayIterObject
*)(iself))->strides[__npy_i]; break; } else { ((PyArrayIterObject
*)(iself))->coordinates[__npy_i] = 0; ((PyArrayIterObject
*)(iself))->dataptr -= ((PyArrayIterObject *)(iself))->
backstrides[__npy_i]; } } } } while (0)
; \
877 PyArray_ITER_NEXT(iother)do { ((PyArrayIterObject *)(iother))->index++; if (((PyArrayIterObject
*)(iother))->nd_m1 == 0) { do { (((PyArrayIterObject *)(iother
)))->dataptr += ((PyArrayIterObject *)(((PyArrayIterObject
*)(iother))))->strides[0]; (((PyArrayIterObject *)(iother
)))->coordinates[0]++; } while (0); } else if (((PyArrayIterObject
*)(iother))->contiguous) ((PyArrayIterObject *)(iother))->
dataptr += PyArray_DESCR(((PyArrayIterObject *)(iother))->
ao)->elsize; else if (((PyArrayIterObject *)(iother))->
nd_m1 == 1) { do { if ((((PyArrayIterObject *)(iother)))->
coordinates[1] < (((PyArrayIterObject *)(iother)))->dims_m1
[1]) { (((PyArrayIterObject *)(iother)))->coordinates[1]++
; (((PyArrayIterObject *)(iother)))->dataptr += (((PyArrayIterObject
*)(iother)))->strides[1]; } else { (((PyArrayIterObject *
)(iother)))->coordinates[1] = 0; (((PyArrayIterObject *)(iother
)))->coordinates[0]++; (((PyArrayIterObject *)(iother)))->
dataptr += (((PyArrayIterObject *)(iother)))->strides[0] -
(((PyArrayIterObject *)(iother)))->backstrides[1]; } } while
(0); } else { int __npy_i; for (__npy_i=((PyArrayIterObject *
)(iother))->nd_m1; __npy_i >= 0; __npy_i--) { if (((PyArrayIterObject
*)(iother))->coordinates[__npy_i] < ((PyArrayIterObject
*)(iother))->dims_m1[__npy_i]) { ((PyArrayIterObject *)(iother
))->coordinates[__npy_i]++; ((PyArrayIterObject *)(iother)
)->dataptr += ((PyArrayIterObject *)(iother))->strides[
__npy_i]; break; } else { ((PyArrayIterObject *)(iother))->
coordinates[__npy_i] = 0; ((PyArrayIterObject *)(iother))->
dataptr -= ((PyArrayIterObject *)(iother))->backstrides[__npy_i
]; } } } } while (0)
; \
878 dptr += 1; \
879 } \
880 }
881
882static int
883_compare_strings(PyArrayObject *result, PyArrayMultiIterObject *multi,
884 int cmp_op, void *func, int rstrip)
885{
886 PyArrayIterObject *iself, *iother;
887 npy_bool *dptr;
888 npy_intp size;
889 int val;
890 int N1, N2;
891 int (*compfunc)(void *, void *, int, int);
892 void (*relfunc)(char *, int);
893 char* (*stripfunc)(char const *, char *, int);
894
895 compfunc = func;
896 dptr = (npy_bool *)PyArray_DATA(result);
897 iself = multi->iters[0];
898 iother = multi->iters[1];
899 size = multi->size;
900 N1 = PyArray_DESCR(iself->ao)->elsize;
901 N2 = PyArray_DESCR(iother->ao)->elsize;
902 if ((void *)compfunc == (void *)_myunincmp) {
903 N1 >>= 2;
904 N2 >>= 2;
905 stripfunc = _uni_copy_n_strip;
906 relfunc = _uni_release;
907 }
908 else {
909 stripfunc = _char_copy_n_strip;
910 relfunc = _char_release;
911 }
912 switch (cmp_op) {
913 case Py_EQ2:
914 if (rstrip) {
915 _rstrip_loop(==);
916 } else {
917 _reg_loop(==);
918 }
919 break;
920 case Py_NE3:
921 if (rstrip) {
922 _rstrip_loop(!=);
923 } else {
924 _reg_loop(!=);
925 }
926 break;
927 case Py_LT0:
928 if (rstrip) {
929 _rstrip_loop(<);
930 } else {
931 _reg_loop(<);
932 }
933 break;
934 case Py_LE1:
935 if (rstrip) {
936 _rstrip_loop(<=);
937 } else {
938 _reg_loop(<=);
939 }
940 break;
941 case Py_GT4:
942 if (rstrip) {
943 _rstrip_loop(>);
944 } else {
945 _reg_loop(>);
946 }
947 break;
948 case Py_GE5:
949 if (rstrip) {
950 _rstrip_loop(>=);
951 } else {
952 _reg_loop(>=);
953 }
954 break;
955 default:
956 PyErr_SetString(PyExc_RuntimeError, "bad comparison operator");
957 return -1;
958 }
959 return 0;
960}
961
962#undef _reg_loop
963#undef _rstrip_loop
964#undef SMALL_STRING
965
966NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
967_strings_richcompare(PyArrayObject *self, PyArrayObject *other, int cmp_op,
968 int rstrip)
969{
970 PyArrayObject *result;
971 PyArrayMultiIterObject *mit;
972 int val;
973
974 /* Cast arrays to a common type */
975 if (PyArray_TYPE(self) != PyArray_DESCR(other)->type_num) {
976 /*
977 * Comparison between Bytes and Unicode is not defined in Py3K;
978 * we follow.
979 */
980 Py_INCREF(Py_NotImplemented)_Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct))));
981 return Py_NotImplemented(&_Py_NotImplementedStruct);
982 }
983 if (PyArray_ISNOTSWAPPED(self)((PyArray_DESCR(self)->byteorder) != '>') != PyArray_ISNOTSWAPPED(other)((PyArray_DESCR(other)->byteorder) != '>')) {
984 PyObject *new;
985 if (PyArray_TYPE(self) == NPY_STRING &&
986 PyArray_DESCR(other)->type_num == NPY_UNICODE) {
987 PyArray_Descr* unicode = PyArray_DescrNew(PyArray_DESCR(other));
988 unicode->elsize = PyArray_DESCR(self)->elsize << 2;
989 new = PyArray_FromAny((PyObject *)self, unicode,
990 0, 0, 0, NULL((void*)0));
991 if (new == NULL((void*)0)) {
992 return NULL((void*)0);
993 }
994 Py_INCREF(other)_Py_INCREF(((PyObject*)(other)));
995 self = (PyArrayObject *)new;
996 }
997 else if ((PyArray_TYPE(self) == NPY_UNICODE) &&
998 ((PyArray_DESCR(other)->type_num == NPY_STRING) ||
999 (PyArray_ISNOTSWAPPED(self)((PyArray_DESCR(self)->byteorder) != '>') != PyArray_ISNOTSWAPPED(other)((PyArray_DESCR(other)->byteorder) != '>')))) {
1000 PyArray_Descr* unicode = PyArray_DescrNew(PyArray_DESCR(self));
1001
1002 if (PyArray_DESCR(other)->type_num == NPY_STRING) {
1003 unicode->elsize = PyArray_DESCR(other)->elsize << 2;
1004 }
1005 else {
1006 unicode->elsize = PyArray_DESCR(other)->elsize;
1007 }
1008 new = PyArray_FromAny((PyObject *)other, unicode,
1009 0, 0, 0, NULL((void*)0));
1010 if (new == NULL((void*)0)) {
1011 return NULL((void*)0);
1012 }
1013 Py_INCREF(self)_Py_INCREF(((PyObject*)(self)));
1014 other = (PyArrayObject *)new;
1015 }
1016 else {
1017 PyErr_SetString(PyExc_TypeError,
1018 "invalid string data-types "
1019 "in comparison");
1020 return NULL((void*)0);
1021 }
1022 }
1023 else {
1024 Py_INCREF(self)_Py_INCREF(((PyObject*)(self)));
1025 Py_INCREF(other)_Py_INCREF(((PyObject*)(other)));
1026 }
1027
1028 /* Broad-cast the arrays to a common shape */
1029 mit = (PyArrayMultiIterObject *)PyArray_MultiIterNew(2, self, other);
1030 Py_DECREF(self)_Py_DECREF(((PyObject*)(self)));
1031 Py_DECREF(other)_Py_DECREF(((PyObject*)(other)));
1032 if (mit == NULL((void*)0)) {
1033 return NULL((void*)0);
1034 }
1035
1036 result = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type,
1037 PyArray_DescrFromType(NPY_BOOL),
1038 mit->nd,
1039 mit->dimensions,
1040 NULL((void*)0), NULL((void*)0), 0,
1041 NULL((void*)0));
1042 if (result == NULL((void*)0)) {
1043 goto finish;
1044 }
1045
1046 if (PyArray_TYPE(self) == NPY_UNICODE) {
1047 val = _compare_strings(result, mit, cmp_op, _myunincmp, rstrip);
1048 }
1049 else {
1050 val = _compare_strings(result, mit, cmp_op, _mystrncmp, rstrip);
1051 }
1052
1053 if (val < 0) {
1054 Py_DECREF(result)_Py_DECREF(((PyObject*)(result)));
1055 result = NULL((void*)0);
1056 }
1057
1058 finish:
1059 Py_DECREF(mit)_Py_DECREF(((PyObject*)(mit)));
1060 return (PyObject *)result;
1061}
1062
1063/*
1064 * VOID-type arrays can only be compared equal and not-equal
1065 * in which case the fields are all compared by extracting the fields
1066 * and testing one at a time...
1067 * equality testing is performed using logical_ands on all the fields.
1068 * in-equality testing is performed using logical_ors on all the fields.
1069 *
1070 * VOID-type arrays without fields are compared for equality by comparing their
1071 * memory at each location directly (using string-code).
1072 */
1073static PyObject *
1074_void_compare(PyArrayObject *self, PyArrayObject *other, int cmp_op)
1075{
1076 if (!(cmp_op == Py_EQ2 || cmp_op == Py_NE3)) {
1077 PyErr_SetString(PyExc_ValueError,
1078 "Void-arrays can only be compared for equality.");
1079 return NULL((void*)0);
1080 }
1081 if (PyArray_HASFIELDS(self)(((PyArray_Descr *)(PyArray_DESCR(self)))->names != ((void
*)0))
) {
1082 PyObject *res = NULL((void*)0), *temp, *a, *b;
1083 PyObject *key, *value, *temp2;
1084 PyObject *op;
1085 Py_ssize_t pos = 0;
1086 npy_intp result_ndim = PyArray_NDIM(self) > PyArray_NDIM(other) ?
1087 PyArray_NDIM(self) : PyArray_NDIM(other);
1088
1089 op = (cmp_op == Py_EQ2 ? n_ops.logical_and : n_ops.logical_or);
1090 while (PyDict_Next(PyArray_DESCR(self)->fields, &pos, &key, &value)) {
1091 if (NPY_TITLE_KEY(key, value)(NPY_TITLE_KEY_check((key), (value)))) {
1092 continue;
1093 }
1094 a = array_subscript_asarray(self, key);
1095 if (a == NULL((void*)0)) {
1096 Py_XDECREF(res)_Py_XDECREF(((PyObject*)(res)));
1097 return NULL((void*)0);
1098 }
1099 b = array_subscript_asarray(other, key);
1100 if (b == NULL((void*)0)) {
1101 Py_XDECREF(res)_Py_XDECREF(((PyObject*)(res)));
1102 Py_DECREF(a)_Py_DECREF(((PyObject*)(a)));
1103 return NULL((void*)0);
1104 }
1105 temp = array_richcompare((PyArrayObject *)a,b,cmp_op);
1106 Py_DECREF(a)_Py_DECREF(((PyObject*)(a)));
1107 Py_DECREF(b)_Py_DECREF(((PyObject*)(b)));
1108 if (temp == NULL((void*)0)) {
1109 Py_XDECREF(res)_Py_XDECREF(((PyObject*)(res)));
1110 return NULL((void*)0);
1111 }
1112
1113 /*
1114 * If the field type has a non-trivial shape, additional
1115 * dimensions will have been appended to `a` and `b`.
1116 * In that case, reduce them using `op`.
1117 */
1118 if (PyArray_Check(temp)((((PyObject*)(temp))->ob_type) == (&PyArray_Type) || PyType_IsSubtype
((((PyObject*)(temp))->ob_type), (&PyArray_Type)))
&&
1119 PyArray_NDIM((PyArrayObject *)temp) > result_ndim) {
1120 /* If the type was multidimensional, collapse that part to 1-D
1121 */
1122 if (PyArray_NDIM((PyArrayObject *)temp) != result_ndim+1) {
1123 npy_intp dimensions[NPY_MAXDIMS32];
1124 PyArray_Dims newdims;
1125
1126 newdims.ptr = dimensions;
1127 newdims.len = result_ndim+1;
1128 if (result_ndim) {
1129 memcpy(dimensions, PyArray_DIMS((PyArrayObject *)temp),
1130 sizeof(npy_intp)*result_ndim);
1131 }
1132 dimensions[result_ndim] = -1;
1133 temp2 = PyArray_Newshape((PyArrayObject *)temp,
1134 &newdims, NPY_ANYORDER);
1135 if (temp2 == NULL((void*)0)) {
1136 Py_DECREF(temp)_Py_DECREF(((PyObject*)(temp)));
1137 Py_XDECREF(res)_Py_XDECREF(((PyObject*)(res)));
1138 return NULL((void*)0);
1139 }
1140 Py_DECREF(temp)_Py_DECREF(((PyObject*)(temp)));
1141 temp = temp2;
1142 }
1143 /* Reduce the extra dimension of `temp` using `op` */
1144 temp2 = PyArray_GenericReduceFunction((PyArrayObject *)temp,
1145 op, result_ndim,
1146 NPY_BOOL, NULL((void*)0));
1147 if (temp2 == NULL((void*)0)) {
1148 Py_DECREF(temp)_Py_DECREF(((PyObject*)(temp)));
1149 Py_XDECREF(res)_Py_XDECREF(((PyObject*)(res)));
1150 return NULL((void*)0);
1151 }
1152 Py_DECREF(temp)_Py_DECREF(((PyObject*)(temp)));
1153 temp = temp2;
1154 }
1155
1156 if (res == NULL((void*)0)) {
1157 res = temp;
1158 }
1159 else {
1160 temp2 = PyObject_CallFunction_PyObject_CallFunction_SizeT(op, "OO", res, temp);
1161 Py_DECREF(temp)_Py_DECREF(((PyObject*)(temp)));
1162 Py_DECREF(res)_Py_DECREF(((PyObject*)(res)));
1163 if (temp2 == NULL((void*)0)) {
1164 return NULL((void*)0);
1165 }
1166 res = temp2;
1167 }
1168 }
1169 if (res == NULL((void*)0) && !PyErr_Occurred()) {
1170 /* these dtypes had no fields. Use a MultiIter to broadcast them
1171 * to an output array, and fill with True (for EQ)*/
1172 PyArrayMultiIterObject *mit = (PyArrayMultiIterObject *)
1173 PyArray_MultiIterNew(2, self, other);
1174 if (mit == NULL((void*)0)) {
1175 return NULL((void*)0);
1176 }
1177
1178 res = PyArray_NewFromDescr(&PyArray_Type,
1179 PyArray_DescrFromType(NPY_BOOL),
1180 mit->nd, mit->dimensions,
1181 NULL((void*)0), NULL((void*)0), 0, NULL((void*)0));
1182 Py_DECREF(mit)_Py_DECREF(((PyObject*)(mit)));
1183 if (res) {
1184 PyArray_FILLWBYTE((PyArrayObject *)res,memset(PyArray_DATA((PyArrayObject *)res), cmp_op == 2 ? 1 : 0
, (PyArray_ITEMSIZE((PyArrayObject *)res) * PyArray_MultiplyList
(PyArray_DIMS((PyArrayObject *)res), PyArray_NDIM((PyArrayObject
*)res))))
1185 cmp_op == Py_EQ ? 1 : 0)memset(PyArray_DATA((PyArrayObject *)res), cmp_op == 2 ? 1 : 0
, (PyArray_ITEMSIZE((PyArrayObject *)res) * PyArray_MultiplyList
(PyArray_DIMS((PyArrayObject *)res), PyArray_NDIM((PyArrayObject
*)res))))
;
1186 }
1187 }
1188 return res;
1189 }
1190 else {
1191 /* compare as a string. Assumes self and other have same descr->type */
1192 return _strings_richcompare(self, other, cmp_op, 0);
1193 }
1194}
1195
1196/*
1197 * Silence the current error and emit a deprecation warning instead.
1198 *
1199 * If warnings are raised as errors, this sets the warning __cause__ to the
1200 * silenced error.
1201 */
1202NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
1203DEPRECATE_silence_error(const char *msg) {
1204 PyObject *exc, *val, *tb;
1205 PyErr_Fetch(&exc, &val, &tb);
1206 if (DEPRECATE(msg)PyErr_WarnEx(PyExc_DeprecationWarning,msg,1) < 0) {
1207 npy_PyErr_ChainExceptionsCause(exc, val, tb);
1208 return -1;
1209 }
1210 Py_XDECREF(exc)_Py_XDECREF(((PyObject*)(exc)));
1211 Py_XDECREF(val)_Py_XDECREF(((PyObject*)(val)));
1212 Py_XDECREF(tb)_Py_XDECREF(((PyObject*)(tb)));
1213 return 0;
1214}
1215
1216/*
1217 * Comparisons can fail, but we do not always want to pass on the exception
1218 * (see comment in array_richcompare below), but rather return NotImplemented.
1219 * Here, an exception should be set on entrance.
1220 * Returns either NotImplemented with the exception cleared, or NULL
1221 * with the exception set.
1222 * Raises deprecation warnings for cases where behaviour is meant to change
1223 * (2015-05-14, 1.10)
1224 */
1225
1226NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
1227_failed_comparison_workaround(PyArrayObject *self, PyObject *other, int cmp_op)
1228{
1229 PyObject *exc, *val, *tb;
1230 PyArrayObject *array_other;
1231 int other_is_flexible, ndim_other;
1232 int self_is_flexible = PyTypeNum_ISFLEXIBLE(PyArray_DESCR(self)->type_num)(((PyArray_DESCR(self)->type_num) >=NPY_STRING) &&
((PyArray_DESCR(self)->type_num) <=NPY_VOID))
;
1233
1234 PyErr_Fetch(&exc, &val, &tb);
1235 /*
1236 * Determine whether other has a flexible dtype; here, inconvertible
1237 * is counted as inflexible. (This repeats work done in the ufunc,
1238 * but OK to waste some time in an unlikely path.)
1239 */
1240 array_other = (PyArrayObject *)PyArray_FROM_O(other)PyArray_FromAny(other, ((void*)0), 0, 0, 0, ((void*)0));
1241 if (array_other) {
1242 other_is_flexible = PyTypeNum_ISFLEXIBLE((((PyArray_DESCR(array_other)->type_num) >=NPY_STRING) &&
((PyArray_DESCR(array_other)->type_num) <=NPY_VOID))
1243 PyArray_DESCR(array_other)->type_num)(((PyArray_DESCR(array_other)->type_num) >=NPY_STRING) &&
((PyArray_DESCR(array_other)->type_num) <=NPY_VOID))
;
1244 ndim_other = PyArray_NDIM(array_other);
1245 Py_DECREF(array_other)_Py_DECREF(((PyObject*)(array_other)));
1246 }
1247 else {
1248 PyErr_Clear(); /* we restore the original error if needed */
1249 other_is_flexible = 0;
1250 ndim_other = 0;
1251 }
1252 if (cmp_op == Py_EQ2 || cmp_op == Py_NE3) {
1253 /*
1254 * note: for == and !=, a structured dtype self cannot get here,
1255 * but a string can. Other can be string or structured.
1256 */
1257 if (other_is_flexible || self_is_flexible) {
1258 /*
1259 * For scalars, returning NotImplemented is correct.
1260 * For arrays, we emit a future deprecation warning.
1261 * When this warning is removed, a correctly shaped
1262 * array of bool should be returned.
1263 */
1264 if (ndim_other != 0 || PyArray_NDIM(self) != 0) {
1265 /* 2015-05-14, 1.10 */
1266 if (DEPRECATE_FUTUREWARNING(PyErr_WarnEx(PyExc_FutureWarning,"elementwise comparison failed; returning scalar "
"instead, but in the future will perform " "elementwise comparison"
,1)
1267 "elementwise comparison failed; returning scalar "PyErr_WarnEx(PyExc_FutureWarning,"elementwise comparison failed; returning scalar "
"instead, but in the future will perform " "elementwise comparison"
,1)
1268 "instead, but in the future will perform "PyErr_WarnEx(PyExc_FutureWarning,"elementwise comparison failed; returning scalar "
"instead, but in the future will perform " "elementwise comparison"
,1)
1269 "elementwise comparison")PyErr_WarnEx(PyExc_FutureWarning,"elementwise comparison failed; returning scalar "
"instead, but in the future will perform " "elementwise comparison"
,1)
< 0) {
1270 goto fail;
1271 }
1272 }
1273 }
1274 else {
1275 /*
1276 * If neither self nor other had a flexible dtype, the error cannot
1277 * have been caused by a lack of implementation in the ufunc.
1278 *
1279 * 2015-05-14, 1.10
1280 */
1281 if (DEPRECATE(PyErr_WarnEx(PyExc_DeprecationWarning,"elementwise comparison failed; "
"this will raise an error in the future.",1)
1282 "elementwise comparison failed; "PyErr_WarnEx(PyExc_DeprecationWarning,"elementwise comparison failed; "
"this will raise an error in the future.",1)
1283 "this will raise an error in the future.")PyErr_WarnEx(PyExc_DeprecationWarning,"elementwise comparison failed; "
"this will raise an error in the future.",1)
< 0) {
1284 goto fail;
1285 }
1286 }
1287 Py_XDECREF(exc)_Py_XDECREF(((PyObject*)(exc)));
1288 Py_XDECREF(val)_Py_XDECREF(((PyObject*)(val)));
1289 Py_XDECREF(tb)_Py_XDECREF(((PyObject*)(tb)));
1290 Py_INCREF(Py_NotImplemented)_Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct))));
1291 return Py_NotImplemented(&_Py_NotImplementedStruct);
1292 }
1293 else if (other_is_flexible || self_is_flexible) {
1294 /*
1295 * For LE, LT, GT, GE and a flexible self or other, we return
1296 * NotImplemented, which is the correct answer since the ufuncs do
1297 * not in fact implement loops for those. This will get us the
1298 * desired TypeError.
1299 */
1300 Py_XDECREF(exc)_Py_XDECREF(((PyObject*)(exc)));
1301 Py_XDECREF(val)_Py_XDECREF(((PyObject*)(val)));
1302 Py_XDECREF(tb)_Py_XDECREF(((PyObject*)(tb)));
1303 Py_INCREF(Py_NotImplemented)_Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct))));
1304 return Py_NotImplemented(&_Py_NotImplementedStruct);
1305 }
1306 else {
1307 /* LE, LT, GT, or GE with non-flexible other; just pass on error */
1308 goto fail;
1309 }
1310
1311fail:
1312 /*
1313 * Reraise the original exception, possibly chaining with a new one.
1314 */
1315 npy_PyErr_ChainExceptionsCause(exc, val, tb);
1316 return NULL((void*)0);
1317}
1318
1319NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject *
1320array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
1321{
1322 PyArrayObject *array_other;
1323 PyObject *obj_self = (PyObject *)self;
1324 PyObject *result = NULL((void*)0);
1325
1326 /* Special case for string arrays (which don't and currently can't have
1327 * ufunc loops defined, so there's no point in trying).
1328 */
1329 if (PyArray_ISSTRING(self)(((PyArray_TYPE(self)) == NPY_STRING) || ((PyArray_TYPE(self)
) == NPY_UNICODE))
) {
1330 array_other = (PyArrayObject *)PyArray_FromObject(other,PyArray_FromAny(other, PyArray_DescrFromType(NPY_NOTYPE), 0, 0
, (0x0100 | 0x0400) | 0x0040, ((void*)0))
1331 NPY_NOTYPE, 0, 0)PyArray_FromAny(other, PyArray_DescrFromType(NPY_NOTYPE), 0, 0
, (0x0100 | 0x0400) | 0x0040, ((void*)0))
;
1332 if (array_other == NULL((void*)0)) {
1333 PyErr_Clear();
1334 /* Never mind, carry on, see what happens */
1335 }
1336 else if (!PyArray_ISSTRING(array_other)(((PyArray_TYPE(array_other)) == NPY_STRING) || ((PyArray_TYPE
(array_other)) == NPY_UNICODE))
) {
1337 Py_DECREF(array_other)_Py_DECREF(((PyObject*)(array_other)));
1338 /* Never mind, carry on, see what happens */
1339 }
1340 else {
1341 result = _strings_richcompare(self, array_other, cmp_op, 0);
1342 Py_DECREF(array_other)_Py_DECREF(((PyObject*)(array_other)));
1343 return result;
1344 }
1345 /* If we reach this point, it means that we are not comparing
1346 * string-to-string. It's possible that this will still work out,
1347 * e.g. if the other array is an object array, then both will be cast
1348 * to object or something? I don't know how that works actually, but
1349 * it does, b/c this works:
1350 * l = ["a", "b"]
1351 * assert np.array(l, dtype="S1") == np.array(l, dtype="O")
1352 * So we fall through and see what happens.
1353 */
1354 }
1355
1356 switch (cmp_op) {
1357 case Py_LT0:
1358 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other)do { if (binop_should_defer((PyObject*)obj_self, (PyObject*)other
, 0)) { _Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct
)))); return (&_Py_NotImplementedStruct); } } while (0)
;
1359 result = PyArray_GenericBinaryFunction(
1360 (PyObject *)self, other, n_ops.less);
1361 break;
1362 case Py_LE1:
1363 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other)do { if (binop_should_defer((PyObject*)obj_self, (PyObject*)other
, 0)) { _Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct
)))); return (&_Py_NotImplementedStruct); } } while (0)
;
1364 result = PyArray_GenericBinaryFunction(
1365 (PyObject *)self, other, n_ops.less_equal);
1366 break;
1367 case Py_EQ2:
1368 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other)do { if (binop_should_defer((PyObject*)obj_self, (PyObject*)other
, 0)) { _Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct
)))); return (&_Py_NotImplementedStruct); } } while (0)
;
1369 /*
1370 * The ufunc does not support void/structured types, so these
1371 * need to be handled specifically. Only a few cases are supported.
1372 */
1373
1374 if (PyArray_TYPE(self) == NPY_VOID) {
1375 int _res;
1376
1377 array_other = (PyArrayObject *)PyArray_FROM_O(other)PyArray_FromAny(other, ((void*)0), 0, 0, 0, ((void*)0));
1378 /*
1379 * If not successful, indicate that the items cannot be compared
1380 * this way.
1381 */
1382 if (array_other == NULL((void*)0)) {
1383 /* 2015-05-07, 1.10 */
1384 if (DEPRECATE_silence_error(
1385 "elementwise == comparison failed and returning scalar "
1386 "instead; this will raise an error in the future.") < 0) {
1387 return NULL((void*)0);
1388 }
1389 Py_INCREF(Py_NotImplemented)_Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct))));
1390 return Py_NotImplemented(&_Py_NotImplementedStruct);
1391 }
1392
1393 _res = PyArray_CanCastTypeTo(PyArray_DESCR(self),
1394 PyArray_DESCR(array_other),
1395 NPY_EQUIV_CASTING);
1396 if (_res == 0) {
1397 /* 2015-05-07, 1.10 */
1398 Py_DECREF(array_other)_Py_DECREF(((PyObject*)(array_other)));
1399 if (DEPRECATE_FUTUREWARNING(PyErr_WarnEx(PyExc_FutureWarning,"elementwise == comparison failed and returning scalar "
"instead; this will raise an error or perform " "elementwise comparison in the future."
,1)
1400 "elementwise == comparison failed and returning scalar "PyErr_WarnEx(PyExc_FutureWarning,"elementwise == comparison failed and returning scalar "
"instead; this will raise an error or perform " "elementwise comparison in the future."
,1)
1401 "instead; this will raise an error or perform "PyErr_WarnEx(PyExc_FutureWarning,"elementwise == comparison failed and returning scalar "
"instead; this will raise an error or perform " "elementwise comparison in the future."
,1)
1402 "elementwise comparison in the future.")PyErr_WarnEx(PyExc_FutureWarning,"elementwise == comparison failed and returning scalar "
"instead; this will raise an error or perform " "elementwise comparison in the future."
,1)
< 0) {
1403 return NULL((void*)0);
1404 }
1405 Py_INCREF(Py_False)_Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct)))
)
;
1406 return Py_False((PyObject *) &_Py_FalseStruct);
1407 }
1408 else {
1409 result = _void_compare(self, array_other, cmp_op);
1410 }
1411 Py_DECREF(array_other)_Py_DECREF(((PyObject*)(array_other)));
1412 return result;
1413 }
1414
1415 result = PyArray_GenericBinaryFunction(
1416 (PyObject *)self, (PyObject *)other, n_ops.equal);
1417 break;
1418 case Py_NE3:
1419 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other)do { if (binop_should_defer((PyObject*)obj_self, (PyObject*)other
, 0)) { _Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct
)))); return (&_Py_NotImplementedStruct); } } while (0)
;
1420 /*
1421 * The ufunc does not support void/structured types, so these
1422 * need to be handled specifically. Only a few cases are supported.
1423 */
1424
1425 if (PyArray_TYPE(self) == NPY_VOID) {
1426 int _res;
1427
1428 array_other = (PyArrayObject *)PyArray_FROM_O(other)PyArray_FromAny(other, ((void*)0), 0, 0, 0, ((void*)0));
1429 /*
1430 * If not successful, indicate that the items cannot be compared
1431 * this way.
1432 */
1433 if (array_other == NULL((void*)0)) {
1434 /* 2015-05-07, 1.10 */
1435 if (DEPRECATE_silence_error(
1436 "elementwise != comparison failed and returning scalar "
1437 "instead; this will raise an error in the future.") < 0) {
1438 return NULL((void*)0);
1439 }
1440 Py_INCREF(Py_NotImplemented)_Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct))));
1441 return Py_NotImplemented(&_Py_NotImplementedStruct);
1442 }
1443
1444 _res = PyArray_CanCastTypeTo(PyArray_DESCR(self),
1445 PyArray_DESCR(array_other),
1446 NPY_EQUIV_CASTING);
1447 if (_res == 0) {
1448 /* 2015-05-07, 1.10 */
1449 Py_DECREF(array_other)_Py_DECREF(((PyObject*)(array_other)));
1450 if (DEPRECATE_FUTUREWARNING(PyErr_WarnEx(PyExc_FutureWarning,"elementwise != comparison failed and returning scalar "
"instead; this will raise an error or perform " "elementwise comparison in the future."
,1)
1451 "elementwise != comparison failed and returning scalar "PyErr_WarnEx(PyExc_FutureWarning,"elementwise != comparison failed and returning scalar "
"instead; this will raise an error or perform " "elementwise comparison in the future."
,1)
1452 "instead; this will raise an error or perform "PyErr_WarnEx(PyExc_FutureWarning,"elementwise != comparison failed and returning scalar "
"instead; this will raise an error or perform " "elementwise comparison in the future."
,1)
1453 "elementwise comparison in the future.")PyErr_WarnEx(PyExc_FutureWarning,"elementwise != comparison failed and returning scalar "
"instead; this will raise an error or perform " "elementwise comparison in the future."
,1)
< 0) {
1454 return NULL((void*)0);
1455 }
1456 Py_INCREF(Py_True)_Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct))));
1457 return Py_True((PyObject *) &_Py_TrueStruct);
1458 }
1459 else {
1460 result = _void_compare(self, array_other, cmp_op);
1461 Py_DECREF(array_other)_Py_DECREF(((PyObject*)(array_other)));
1462 }
1463 return result;
1464 }
1465
1466 result = PyArray_GenericBinaryFunction(
1467 (PyObject *)self, (PyObject *)other, n_ops.not_equal);
1468 break;
1469 case Py_GT4:
1470 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other)do { if (binop_should_defer((PyObject*)obj_self, (PyObject*)other
, 0)) { _Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct
)))); return (&_Py_NotImplementedStruct); } } while (0)
;
1471 result = PyArray_GenericBinaryFunction(
1472 (PyObject *)self, other, n_ops.greater);
1473 break;
1474 case Py_GE5:
1475 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other)do { if (binop_should_defer((PyObject*)obj_self, (PyObject*)other
, 0)) { _Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct
)))); return (&_Py_NotImplementedStruct); } } while (0)
;
1476 result = PyArray_GenericBinaryFunction(
1477 (PyObject *)self, other, n_ops.greater_equal);
1478 break;
1479 default:
1480 Py_INCREF(Py_NotImplemented)_Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct))));
1481 return Py_NotImplemented(&_Py_NotImplementedStruct);
1482 }
1483 if (result == NULL((void*)0)) {
1484 /*
1485 * 2015-05-14, 1.10; updated 2018-06-18, 1.16.
1486 *
1487 * Comparisons can raise errors when element-wise comparison is not
1488 * possible. Some of these, though, should not be passed on.
1489 * In particular, the ufuncs do not have loops for flexible dtype,
1490 * so those should be treated separately. Furthermore, for EQ and NE,
1491 * we should never fail.
1492 *
1493 * Our ideal behaviour would be:
1494 *
1495 * 1. For EQ and NE:
1496 * - If self and other are scalars, return NotImplemented,
1497 * so that python can assign True of False as appropriate.
1498 * - If either is an array, return an array of False or True.
1499 *
1500 * 2. For LT, LE, GE, GT:
1501 * - If self or other was flexible, return NotImplemented
1502 * (as is in fact the case), so python can raise a TypeError.
1503 * - If other is not convertible to an array, pass on the error
1504 * (MHvK, 2018-06-18: not sure about this, but it's what we have).
1505 *
1506 * However, for backwards compatibility, we cannot yet return arrays,
1507 * so we raise warnings instead.
1508 */
1509 result = _failed_comparison_workaround(self, other, cmp_op);
1510 }
1511 return result;
1512}
1513
1514/*NUMPY_API
1515 */
1516NPY_NO_EXPORT__attribute__((visibility("hidden"))) int
1517PyArray_ElementStrides(PyObject *obj)
1518{
1519 PyArrayObject *arr;
1520 int itemsize;
1521 int i, ndim;
1522 npy_intp *strides;
1523
1524 if (!PyArray_Check(obj)((((PyObject*)(obj))->ob_type) == (&PyArray_Type) || PyType_IsSubtype
((((PyObject*)(obj))->ob_type), (&PyArray_Type)))
) {
1525 return 0;
1526 }
1527
1528 arr = (PyArrayObject *)obj;
1529
1530 itemsize = PyArray_ITEMSIZE(arr);
1531 ndim = PyArray_NDIM(arr);
1532 strides = PyArray_STRIDES(arr);
1533
1534 for (i = 0; i < ndim; i++) {
1535 if ((strides[i] % itemsize) != 0) {
1536 return 0;
1537 }
1538 }
1539 return 1;
1540}
1541
1542/*
1543 * This routine checks to see if newstrides (of length nd) will not
1544 * ever be able to walk outside of the memory implied numbytes and offset.
1545 *
1546 * The available memory is assumed to start at -offset and proceed
1547 * to numbytes-offset. The strides are checked to ensure
1548 * that accessing memory using striding will not try to reach beyond
1549 * this memory for any of the axes.
1550 *
1551 * If numbytes is 0 it will be calculated using the dimensions and
1552 * element-size.
1553 *
1554 * This function checks for walking beyond the beginning and right-end
1555 * of the buffer and therefore works for any integer stride (positive
1556 * or negative).
1557 */
1558
1559/*NUMPY_API*/
1560NPY_NO_EXPORT__attribute__((visibility("hidden"))) npy_bool
1561PyArray_CheckStrides(int elsize, int nd, npy_intp numbytes, npy_intp offset,
1562 npy_intp const *dims, npy_intp const *newstrides)
1563{
1564 npy_intp begin, end;
1565 npy_intp lower_offset;
1566 npy_intp upper_offset;
1567
1568 if (numbytes == 0) {
1569 numbytes = PyArray_MultiplyList(dims, nd) * elsize;
1570 }
1571
1572 begin = -offset;
1573 end = numbytes - offset;
1574
1575 offset_bounds_from_strides(elsize, nd, dims, newstrides,
1576 &lower_offset, &upper_offset);
1577
1578 if ((upper_offset > end) || (lower_offset < begin)) {
1579 return NPY_FALSE0;
1580 }
1581 return NPY_TRUE1;
1582}
1583
1584
1585static PyObject *
1586array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
1587{
1588 static char *kwlist[] = {"shape", "dtype", "buffer", "offset", "strides",
1589 "order", NULL((void*)0)};
1590 PyArray_Descr *descr = NULL((void*)0);
1591 int itemsize;
1592 PyArray_Dims dims = {NULL((void*)0), 0};
1593 PyArray_Dims strides = {NULL((void*)0), -1};
1594 PyArray_Chunk buffer;
1595 npy_longlong offset = 0;
1596 NPY_ORDER order = NPY_CORDER;
1597 int is_f_order = 0;
1598 PyArrayObject *ret;
1599
1600 buffer.ptr = NULL((void*)0);
1601 /*
1602 * Usually called with shape and type but can also be called with buffer,
1603 * strides, and swapped info For now, let's just use this to create an
1604 * empty, contiguous array of a specific type and shape.
1605 */
1606 if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, kwds, "O&|O&O&LO&O&:ndarray",
1607 kwlist, PyArray_IntpConverter,
1608 &dims,
1609 PyArray_DescrConverter,
1610 &descr,
1611 PyArray_BufferConverter,
1612 &buffer,
1613 &offset,
1614 &PyArray_OptionalIntpConverter,
1615 &strides,
1616 &PyArray_OrderConverter,
1617 &order)) {
1618 goto fail;
1619 }
1620 if (order == NPY_FORTRANORDER) {
1621 is_f_order = 1;
1622 }
1623 if (descr == NULL((void*)0)) {
1624 descr = PyArray_DescrFromType(NPY_DEFAULT_TYPENPY_DOUBLE);
1625 }
1626
1627 itemsize = descr->elsize;
1628
1629 if (strides.len != -1) {
1630 npy_intp nb, off;
1631 if (strides.len != dims.len) {
1632 PyErr_SetString(PyExc_ValueError,
1633 "strides, if given, must be " \
1634 "the same length as shape");
1635 goto fail;
1636 }
1637
1638 if (buffer.ptr == NULL((void*)0)) {
1639 nb = 0;
1640 off = 0;
1641 }
1642 else {
1643 nb = buffer.len;
1644 off = (npy_intp) offset;
1645 }
1646
1647
1648 if (!PyArray_CheckStrides(itemsize, dims.len,
1649 nb, off,
1650 dims.ptr, strides.ptr)) {
1651 PyErr_SetString(PyExc_ValueError,
1652 "strides is incompatible " \
1653 "with shape of requested " \
1654 "array and size of buffer");
1655 goto fail;
1656 }
1657 }
1658
1659 if (buffer.ptr == NULL((void*)0)) {
1660 ret = (PyArrayObject *)
1661 PyArray_NewFromDescr_int(subtype, descr,
1662 (int)dims.len,
1663 dims.ptr,
1664 strides.ptr, NULL((void*)0), is_f_order, NULL((void*)0), NULL((void*)0),
1665 0, 1);
1666 if (ret == NULL((void*)0)) {
1667 descr = NULL((void*)0);
1668 goto fail;
1669 }
1670 if (PyDataType_FLAGCHK(descr, NPY_ITEM_HASOBJECT)(((descr)->flags & (0x01)) == (0x01))) {
1671 /* place Py_None in object positions */
1672 PyArray_FillObjectArray(ret, Py_None(&_Py_NoneStruct));
1673 if (PyErr_Occurred()) {
1674 descr = NULL((void*)0);
1675 goto fail;
1676 }
1677 }
1678 }
1679 else {
1680 /* buffer given -- use it */
1681 if (dims.len == 1 && dims.ptr[0] == -1) {
1682 dims.ptr[0] = (buffer.len-(npy_intp)offset) / itemsize;
1683 }
1684 else if ((strides.ptr == NULL((void*)0)) &&
1685 (buffer.len < (offset + (((npy_intp)itemsize)*
1686 PyArray_MultiplyList(dims.ptr,
1687 dims.len))))) {
1688 PyErr_SetString(PyExc_TypeError,
1689 "buffer is too small for " \
1690 "requested array");
1691 goto fail;
1692 }
1693 /* get writeable and aligned */
1694 if (is_f_order) {
1695 buffer.flags |= NPY_ARRAY_F_CONTIGUOUS0x0002;
1696 }
1697 ret = (PyArrayObject *)PyArray_NewFromDescr_int(
1698 subtype, descr,
1699 dims.len, dims.ptr, strides.ptr, offset + (char *)buffer.ptr,
1700 buffer.flags, NULL((void*)0), buffer.base,
1701 0, 1);
1702 if (ret == NULL((void*)0)) {
1703 descr = NULL((void*)0);
1704 goto fail;
1705 }
1706 }
1707
1708 npy_free_cache_dim_obj(dims);
1709 npy_free_cache_dim_obj(strides);
1710 return (PyObject *)ret;
1711
1712 fail:
1713 Py_XDECREF(descr)_Py_XDECREF(((PyObject*)(descr)));
1714 npy_free_cache_dim_obj(dims);
1715 npy_free_cache_dim_obj(strides);
1716 return NULL((void*)0);
1717}
1718
1719
1720static PyObject *
1721array_iter(PyArrayObject *arr)
1722{
1723 if (PyArray_NDIM(arr) == 0) {
1724 PyErr_SetString(PyExc_TypeError,
1725 "iteration over a 0-d array");
1726 return NULL((void*)0);
1727 }
1728 return PySeqIter_New((PyObject *)arr);
1729}
1730
1731static PyObject *
1732array_alloc(PyTypeObject *type, Py_ssize_t NPY_UNUSED(nitems)(__NPY_UNUSED_TAGGEDnitems) __attribute__ ((__unused__)))
1733{
1734 /* nitems will always be 0 */
1735 PyObject *obj = PyObject_Malloc(type->tp_basicsize);
1736 PyObject_Init(obj, type);
1737 return obj;
1738}
1739
1740static void
1741array_free(PyObject * v)
1742{
1743 /* avoid same deallocator as PyBaseObject, see gentype_free */
1744 PyObject_Free(v);
1745}
1746
1747
1748NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyTypeObject PyArray_Type = {
1749 PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 },
1750 .tp_name = "numpy.ndarray",
1751 .tp_basicsize = sizeof(PyArrayObject_fields),
1752 /* methods */
1753 .tp_dealloc = (destructor)array_dealloc,
1754 .tp_repr = (reprfunc)array_repr,
1755 .tp_as_number = &array_as_number,
1756 .tp_as_sequence = &array_as_sequence,
1757 .tp_as_mapping = &array_as_mapping,
1758 .tp_str = (reprfunc)array_str,
1759 .tp_as_buffer = &array_as_buffer,
1760 .tp_flags =(Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0) | Py_TPFLAGS_BASETYPE(1UL << 10)),
1761
1762 .tp_richcompare = (richcmpfunc)array_richcompare,
1763 .tp_weaklistoffset = offsetof(PyArrayObject_fields, weakreflist)__builtin_offsetof(PyArrayObject_fields, weakreflist),
1764 .tp_iter = (getiterfunc)array_iter,
1765 .tp_methods = array_methods,
1766 .tp_getset = array_getsetlist,
1767 .tp_alloc = (allocfunc)array_alloc,
1768 .tp_new = (newfunc)array_new,
1769 .tp_free = (freefunc)array_free,
1770};

/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)((PyArray_DTypeMeta *)(((PyObject*)(legacy_descr))->ob_type
))
;
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)((PyArray_DTypeMeta *)(((PyObject*)(descr))->ob_type)));
418 if (DType == NULL((void*)0)) {
419 return -1;
420 }
421 if (DType == NPY_DTYPE(descr)((PyArray_DTypeMeta *)(((PyObject*)(descr))->ob_type)) || 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)
) {
10
Taking true branch
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) {
11
Assuming the condition is true
12
Assuming the condition is true
13
Taking true branch
887 goto force_sequence_due_to_char_dtype;
14
Control jumps to line 1075
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");
15
Calling 'PySequence_Fast'
17
Returning from 'PySequence_Fast'
21
PyObject ownership leak with reference count of 1
1076 if (seq == NULL((void*)0)) {
18
Assuming 'seq' is not equal to NULL
19
Taking false branch
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) {
20
Taking true branch
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)) {
2
Assuming 'fixed_DType' is equal to NULL
3
Taking false branch
1184 assert(PyObject_TypeCheck(((void) (0))
1185 (PyObject *)fixed_DType, (PyTypeObject *)&PyArrayDTypeMeta_Type))((void) (0));
1186 }
1187
1188 if (requested_descr
3.1
'requested_descr' is not equal to NULL
3.1
'requested_descr' is not equal to NULL
3.1
'requested_descr' is not equal to NULL
!= NULL((void*)0)) {
4
Taking true branch
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
4.1
'requested_descr' is not equal to NULL
4.1
'requested_descr' is not equal to NULL
4.1
'requested_descr' is not equal to NULL
!= NULL((void*)0)) {
5
Taking true branch
1203 if (requested_descr->type_num == NPY_STRING &&
6
Assuming field 'type_num' is equal to NPY_STRING
8
Taking true branch
1204 requested_descr->type == 'c') {
7
Assuming the condition is true
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(
9
Calling '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)) {
1446 if (PyObject_TypeCheck(dtype, (PyTypeObject *)&PyArrayDTypeMeta_Type)((((PyObject*)(dtype))->ob_type) == ((PyTypeObject *)&
PyArrayDTypeMeta_Type) || PyType_IsSubtype((((PyObject*)(dtype
))->ob_type), ((PyTypeObject *)&PyArrayDTypeMeta_Type)
))
) {
1447 assert(dtype != (PyObject * )&PyArrayDescr_Type)((void) (0)); /* not np.dtype */
1448 *out_DType = (PyArray_DTypeMeta *)dtype;
1449 Py_INCREF(*out_DType)_Py_INCREF(((PyObject*)(*out_DType)));
1450 }
1451 else if (PyObject_TypeCheck((PyObject *)Py_TYPE(dtype),((((PyObject*)((PyObject *)(((PyObject*)(dtype))->ob_type)
))->ob_type) == ((PyTypeObject *)&PyArrayDTypeMeta_Type
) || PyType_IsSubtype((((PyObject*)((PyObject *)(((PyObject*)
(dtype))->ob_type)))->ob_type), ((PyTypeObject *)&PyArrayDTypeMeta_Type
)))
1452 (PyTypeObject *)&PyArrayDTypeMeta_Type)((((PyObject*)((PyObject *)(((PyObject*)(dtype))->ob_type)
))->ob_type) == ((PyTypeObject *)&PyArrayDTypeMeta_Type
) || PyType_IsSubtype((((PyObject*)((PyObject *)(((PyObject*)
(dtype))->ob_type)))->ob_type), ((PyTypeObject *)&PyArrayDTypeMeta_Type
)))
) {
1453 *out_DType = NPY_DTYPE(dtype)((PyArray_DTypeMeta *)(((PyObject*)(dtype))->ob_type));
1454 Py_INCREF(*out_DType)_Py_INCREF(((PyObject*)(*out_DType)));
1455 if (!descr_is_legacy_parametric_instance((PyArray_Descr *)dtype)) {
1456 *out_descr = (PyArray_Descr *)dtype;
1457 Py_INCREF(*out_descr)_Py_INCREF(((PyObject*)(*out_descr)));
1458 }
1459 }
1460 else {
1461 PyErr_SetString(PyExc_TypeError,
1462 "dtype parameter must be a DType instance or class.");
1463 return -1;
1464 }
1465 }
1466 return 0;
1467}
1468
1469
1470/*
1471 * Python API function to expose the dtype+shape discovery functionality
1472 * directly.
1473 */
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/PySequence_Fast.model

1#ifndef PySequence_Fast
2struct _object;
3typedef struct _object PyObject;
4PyObject* clang_analyzer_PyObject_New_Reference();
5PyObject* PySequence_Fast(PyObject *o, const char *m) {
6 return clang_analyzer_PyObject_New_Reference();
16
Setting reference count to 1
7}
8#else
9#warning "API PySequence_Fast is defined as a macro."
10#endif