File: | numpy/core/src/multiarray/nditer_pywrap.c |
Warning: | line 1596, column 27 PyObject ownership leak with reference count of 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * This file implements the CPython wrapper of NpyIter | |||
3 | * | |||
4 | * Copyright (c) 2010 by Mark Wiebe (mwwiebe@gmail.com) | |||
5 | * The University of British Columbia | |||
6 | * | |||
7 | * See LICENSE.txt for the license. | |||
8 | */ | |||
9 | #define PY_SSIZE_T_CLEAN | |||
10 | #include "Python.h" | |||
11 | #include "structmember.h" | |||
12 | ||||
13 | #define NPY_NO_DEPRECATED_API0x0000000E NPY_API_VERSION0x0000000E | |||
14 | #define _MULTIARRAYMODULE | |||
15 | #include <numpy/arrayobject.h> | |||
16 | #include "npy_config.h" | |||
17 | #include "npy_pycompat.h" | |||
18 | #include "alloc.h" | |||
19 | #include "common.h" | |||
20 | #include "conversion_utils.h" | |||
21 | #include "ctors.h" | |||
22 | ||||
23 | /* Functions not part of the public NumPy C API */ | |||
24 | npy_bool npyiter_has_writeback(NpyIter *iter); | |||
25 | ||||
26 | ||||
27 | typedef struct NewNpyArrayIterObject_tag NewNpyArrayIterObject; | |||
28 | ||||
29 | struct NewNpyArrayIterObject_tag { | |||
30 | PyObject_HEADPyObject ob_base; | |||
31 | /* The iterator */ | |||
32 | NpyIter *iter; | |||
33 | /* Flag indicating iteration started/stopped */ | |||
34 | char started, finished; | |||
35 | /* Child to update for nested iteration */ | |||
36 | NewNpyArrayIterObject *nested_child; | |||
37 | /* Cached values from the iterator */ | |||
38 | NpyIter_IterNextFunc *iternext; | |||
39 | NpyIter_GetMultiIndexFunc *get_multi_index; | |||
40 | char **dataptrs; | |||
41 | PyArray_Descr **dtypes; | |||
42 | PyArrayObject **operands; | |||
43 | npy_intp *innerstrides, *innerloopsizeptr; | |||
44 | char readflags[NPY_MAXARGS32]; | |||
45 | char writeflags[NPY_MAXARGS32]; | |||
46 | }; | |||
47 | ||||
48 | static int npyiter_cache_values(NewNpyArrayIterObject *self) | |||
49 | { | |||
50 | NpyIter *iter = self->iter; | |||
51 | ||||
52 | /* iternext and get_multi_index functions */ | |||
53 | self->iternext = NpyIter_GetIterNext(iter, NULL((void*)0)); | |||
54 | if (self->iternext == NULL((void*)0)) { | |||
55 | return -1; | |||
56 | } | |||
57 | ||||
58 | if (NpyIter_HasMultiIndex(iter) && !NpyIter_HasDelayedBufAlloc(iter)) { | |||
59 | self->get_multi_index = NpyIter_GetGetMultiIndex(iter, NULL((void*)0)); | |||
60 | } | |||
61 | else { | |||
62 | self->get_multi_index = NULL((void*)0); | |||
63 | } | |||
64 | ||||
65 | /* Internal data pointers */ | |||
66 | self->dataptrs = NpyIter_GetDataPtrArray(iter); | |||
67 | self->dtypes = NpyIter_GetDescrArray(iter); | |||
68 | self->operands = NpyIter_GetOperandArray(iter); | |||
69 | ||||
70 | if (NpyIter_HasExternalLoop(iter)) { | |||
71 | self->innerstrides = NpyIter_GetInnerStrideArray(iter); | |||
72 | self->innerloopsizeptr = NpyIter_GetInnerLoopSizePtr(iter); | |||
73 | } | |||
74 | else { | |||
75 | self->innerstrides = NULL((void*)0); | |||
76 | self->innerloopsizeptr = NULL((void*)0); | |||
77 | } | |||
78 | ||||
79 | /* The read/write settings */ | |||
80 | NpyIter_GetReadFlags(iter, self->readflags); | |||
81 | NpyIter_GetWriteFlags(iter, self->writeflags); | |||
82 | return 0; | |||
83 | } | |||
84 | ||||
85 | static PyObject * | |||
86 | npyiter_new(PyTypeObject *subtype, PyObject *NPY_UNUSED(args)(__NPY_UNUSED_TAGGEDargs) __attribute__ ((__unused__)), | |||
87 | PyObject *NPY_UNUSED(kwds)(__NPY_UNUSED_TAGGEDkwds) __attribute__ ((__unused__))) | |||
88 | { | |||
89 | NewNpyArrayIterObject *self; | |||
90 | ||||
91 | self = (NewNpyArrayIterObject *)subtype->tp_alloc(subtype, 0); | |||
92 | if (self != NULL((void*)0)) { | |||
93 | self->iter = NULL((void*)0); | |||
94 | self->nested_child = NULL((void*)0); | |||
95 | } | |||
96 | ||||
97 | return (PyObject *)self; | |||
98 | } | |||
99 | ||||
100 | static int | |||
101 | NpyIter_GlobalFlagsConverter(PyObject *flags_in, npy_uint32 *flags) | |||
102 | { | |||
103 | npy_uint32 tmpflags = 0; | |||
104 | int iflags, nflags; | |||
105 | ||||
106 | PyObject *f; | |||
107 | char *str = NULL((void*)0); | |||
108 | Py_ssize_t length = 0; | |||
109 | npy_uint32 flag; | |||
110 | ||||
111 | if (flags_in == NULL((void*)0) || flags_in == Py_None(&_Py_NoneStruct)) { | |||
112 | return 1; | |||
113 | } | |||
114 | ||||
115 | if (!PyTuple_Check(flags_in)((((((PyObject*)(flags_in))->ob_type))->tp_flags & ( (1UL << 26))) != 0) && !PyList_Check(flags_in)((((((PyObject*)(flags_in))->ob_type))->tp_flags & ( (1UL << 25))) != 0)) { | |||
116 | PyErr_SetString(PyExc_ValueError, | |||
117 | "Iterator global flags must be a list or tuple of strings"); | |||
118 | return 0; | |||
119 | } | |||
120 | ||||
121 | nflags = PySequence_Size(flags_in); | |||
122 | ||||
123 | for (iflags = 0; iflags < nflags; ++iflags) { | |||
124 | f = PySequence_GetItem(flags_in, iflags); | |||
125 | if (f == NULL((void*)0)) { | |||
126 | return 0; | |||
127 | } | |||
128 | ||||
129 | if (PyUnicode_Check(f)((((((PyObject*)(f))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
130 | /* accept unicode input */ | |||
131 | PyObject *f_str; | |||
132 | f_str = PyUnicode_AsASCIIString(f); | |||
133 | if (f_str == NULL((void*)0)) { | |||
134 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
135 | return 0; | |||
136 | } | |||
137 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
138 | f = f_str; | |||
139 | } | |||
140 | ||||
141 | if (PyBytes_AsStringAndSize(f, &str, &length) < 0) { | |||
142 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
143 | return 0; | |||
144 | } | |||
145 | /* Use switch statements to quickly isolate the right flag */ | |||
146 | flag = 0; | |||
147 | switch (str[0]) { | |||
148 | case 'b': | |||
149 | if (strcmp(str, "buffered") == 0) { | |||
150 | flag = NPY_ITER_BUFFERED0x00000200; | |||
151 | } | |||
152 | break; | |||
153 | case 'c': | |||
154 | if (length >= 6) switch (str[5]) { | |||
155 | case 'e': | |||
156 | if (strcmp(str, "c_index") == 0) { | |||
157 | flag = NPY_ITER_C_INDEX0x00000001; | |||
158 | } | |||
159 | break; | |||
160 | case 'i': | |||
161 | if (strcmp(str, "copy_if_overlap") == 0) { | |||
162 | flag = NPY_ITER_COPY_IF_OVERLAP0x00002000; | |||
163 | } | |||
164 | break; | |||
165 | case 'n': | |||
166 | if (strcmp(str, "common_dtype") == 0) { | |||
167 | flag = NPY_ITER_COMMON_DTYPE0x00000010; | |||
168 | } | |||
169 | break; | |||
170 | } | |||
171 | break; | |||
172 | case 'd': | |||
173 | if (strcmp(str, "delay_bufalloc") == 0) { | |||
174 | flag = NPY_ITER_DELAY_BUFALLOC0x00000800; | |||
175 | } | |||
176 | break; | |||
177 | case 'e': | |||
178 | if (strcmp(str, "external_loop") == 0) { | |||
179 | flag = NPY_ITER_EXTERNAL_LOOP0x00000008; | |||
180 | } | |||
181 | break; | |||
182 | case 'f': | |||
183 | if (strcmp(str, "f_index") == 0) { | |||
184 | flag = NPY_ITER_F_INDEX0x00000002; | |||
185 | } | |||
186 | break; | |||
187 | case 'g': | |||
188 | /* | |||
189 | * Documentation is grow_inner, but initial implementation | |||
190 | * was growinner, so allowing for either. | |||
191 | */ | |||
192 | if (strcmp(str, "grow_inner") == 0 || | |||
193 | strcmp(str, "growinner") == 0) { | |||
194 | flag = NPY_ITER_GROWINNER0x00000400; | |||
195 | } | |||
196 | break; | |||
197 | case 'm': | |||
198 | if (strcmp(str, "multi_index") == 0) { | |||
199 | flag = NPY_ITER_MULTI_INDEX0x00000004; | |||
200 | } | |||
201 | break; | |||
202 | case 'r': | |||
203 | if (strcmp(str, "ranged") == 0) { | |||
204 | flag = NPY_ITER_RANGED0x00000100; | |||
205 | } | |||
206 | else if (strcmp(str, "refs_ok") == 0) { | |||
207 | flag = NPY_ITER_REFS_OK0x00000020; | |||
208 | } | |||
209 | else if (strcmp(str, "reduce_ok") == 0) { | |||
210 | flag = NPY_ITER_REDUCE_OK0x00000080; | |||
211 | } | |||
212 | break; | |||
213 | case 'z': | |||
214 | if (strcmp(str, "zerosize_ok") == 0) { | |||
215 | flag = NPY_ITER_ZEROSIZE_OK0x00000040; | |||
216 | } | |||
217 | break; | |||
218 | } | |||
219 | if (flag == 0) { | |||
220 | PyErr_Format(PyExc_ValueError, | |||
221 | "Unexpected iterator global flag \"%s\"", str); | |||
222 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
223 | return 0; | |||
224 | } | |||
225 | else { | |||
226 | tmpflags |= flag; | |||
227 | } | |||
228 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
229 | } | |||
230 | ||||
231 | *flags |= tmpflags; | |||
232 | return 1; | |||
233 | } | |||
234 | ||||
235 | static int | |||
236 | NpyIter_OpFlagsConverter(PyObject *op_flags_in, | |||
237 | npy_uint32 *op_flags) | |||
238 | { | |||
239 | int iflags, nflags; | |||
240 | npy_uint32 flag; | |||
241 | ||||
242 | if (!PyTuple_Check(op_flags_in)((((((PyObject*)(op_flags_in))->ob_type))->tp_flags & ((1UL << 26))) != 0) && !PyList_Check(op_flags_in)((((((PyObject*)(op_flags_in))->ob_type))->tp_flags & ((1UL << 25))) != 0)) { | |||
243 | PyErr_SetString(PyExc_ValueError, | |||
244 | "op_flags must be a tuple or array of per-op flag-tuples"); | |||
245 | return 0; | |||
246 | } | |||
247 | ||||
248 | nflags = PySequence_Size(op_flags_in); | |||
249 | ||||
250 | *op_flags = 0; | |||
251 | for (iflags = 0; iflags < nflags; ++iflags) { | |||
252 | PyObject *f; | |||
253 | char *str = NULL((void*)0); | |||
254 | Py_ssize_t length = 0; | |||
255 | ||||
256 | f = PySequence_GetItem(op_flags_in, iflags); | |||
257 | if (f == NULL((void*)0)) { | |||
258 | return 0; | |||
259 | } | |||
260 | ||||
261 | if (PyUnicode_Check(f)((((((PyObject*)(f))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
262 | /* accept unicode input */ | |||
263 | PyObject *f_str; | |||
264 | f_str = PyUnicode_AsASCIIString(f); | |||
265 | if (f_str == NULL((void*)0)) { | |||
266 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
267 | return 0; | |||
268 | } | |||
269 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
270 | f = f_str; | |||
271 | } | |||
272 | ||||
273 | if (PyBytes_AsStringAndSize(f, &str, &length) < 0) { | |||
274 | PyErr_Clear(); | |||
275 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
276 | PyErr_SetString(PyExc_ValueError, | |||
277 | "op_flags must be a tuple or array of per-op flag-tuples"); | |||
278 | return 0; | |||
279 | } | |||
280 | ||||
281 | /* Use switch statements to quickly isolate the right flag */ | |||
282 | flag = 0; | |||
283 | switch (str[0]) { | |||
284 | case 'a': | |||
285 | if (length > 2) switch(str[2]) { | |||
286 | case 'i': | |||
287 | if (strcmp(str, "aligned") == 0) { | |||
288 | flag = NPY_ITER_ALIGNED0x00100000; | |||
289 | } | |||
290 | break; | |||
291 | case 'l': | |||
292 | if (strcmp(str, "allocate") == 0) { | |||
293 | flag = NPY_ITER_ALLOCATE0x01000000; | |||
294 | } | |||
295 | break; | |||
296 | case 'r': | |||
297 | if (strcmp(str, "arraymask") == 0) { | |||
298 | flag = NPY_ITER_ARRAYMASK0x20000000; | |||
299 | } | |||
300 | break; | |||
301 | } | |||
302 | break; | |||
303 | case 'c': | |||
304 | if (strcmp(str, "copy") == 0) { | |||
305 | flag = NPY_ITER_COPY0x00400000; | |||
306 | } | |||
307 | if (strcmp(str, "contig") == 0) { | |||
308 | flag = NPY_ITER_CONTIG0x00200000; | |||
309 | } | |||
310 | break; | |||
311 | case 'n': | |||
312 | switch (str[1]) { | |||
313 | case 'b': | |||
314 | if (strcmp(str, "nbo") == 0) { | |||
315 | flag = NPY_ITER_NBO0x00080000; | |||
316 | } | |||
317 | break; | |||
318 | case 'o': | |||
319 | if (strcmp(str, "no_subtype") == 0) { | |||
320 | flag = NPY_ITER_NO_SUBTYPE0x02000000; | |||
321 | } | |||
322 | else if (strcmp(str, "no_broadcast") == 0) { | |||
323 | flag = NPY_ITER_NO_BROADCAST0x08000000; | |||
324 | } | |||
325 | break; | |||
326 | } | |||
327 | break; | |||
328 | case 'o': | |||
329 | if (strcmp(str, "overlap_assume_elementwise") == 0) { | |||
330 | flag = NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE0x40000000; | |||
331 | } | |||
332 | break; | |||
333 | case 'r': | |||
334 | if (length > 4) switch (str[4]) { | |||
335 | case 'o': | |||
336 | if (strcmp(str, "readonly") == 0) { | |||
337 | flag = NPY_ITER_READONLY0x00020000; | |||
338 | } | |||
339 | break; | |||
340 | case 'w': | |||
341 | if (strcmp(str, "readwrite") == 0) { | |||
342 | flag = NPY_ITER_READWRITE0x00010000; | |||
343 | } | |||
344 | break; | |||
345 | } | |||
346 | break; | |||
347 | case 'u': | |||
348 | switch (str[1]) { | |||
349 | case 'p': | |||
350 | if (strcmp(str, "updateifcopy") == 0) { | |||
351 | flag = NPY_ITER_UPDATEIFCOPY0x00800000; | |||
352 | } | |||
353 | break; | |||
354 | } | |||
355 | break; | |||
356 | case 'v': | |||
357 | if (strcmp(str, "virtual") == 0) { | |||
358 | flag = NPY_ITER_VIRTUAL0x04000000; | |||
359 | } | |||
360 | break; | |||
361 | case 'w': | |||
362 | if (length > 5) switch (str[5]) { | |||
363 | case 'o': | |||
364 | if (strcmp(str, "writeonly") == 0) { | |||
365 | flag = NPY_ITER_WRITEONLY0x00040000; | |||
366 | } | |||
367 | break; | |||
368 | case 'm': | |||
369 | if (strcmp(str, "writemasked") == 0) { | |||
370 | flag = NPY_ITER_WRITEMASKED0x10000000; | |||
371 | } | |||
372 | break; | |||
373 | } | |||
374 | break; | |||
375 | } | |||
376 | if (flag == 0) { | |||
377 | PyErr_Format(PyExc_ValueError, | |||
378 | "Unexpected per-op iterator flag \"%s\"", str); | |||
379 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
380 | return 0; | |||
381 | } | |||
382 | else { | |||
383 | *op_flags |= flag; | |||
384 | } | |||
385 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
386 | } | |||
387 | ||||
388 | return 1; | |||
389 | } | |||
390 | ||||
391 | static int | |||
392 | npyiter_convert_op_flags_array(PyObject *op_flags_in, | |||
393 | npy_uint32 *op_flags_array, npy_intp nop) | |||
394 | { | |||
395 | npy_intp iop; | |||
396 | ||||
397 | if (!PyTuple_Check(op_flags_in)((((((PyObject*)(op_flags_in))->ob_type))->tp_flags & ((1UL << 26))) != 0) && !PyList_Check(op_flags_in)((((((PyObject*)(op_flags_in))->ob_type))->tp_flags & ((1UL << 25))) != 0)) { | |||
398 | PyErr_SetString(PyExc_ValueError, | |||
399 | "op_flags must be a tuple or array of per-op flag-tuples"); | |||
400 | return 0; | |||
401 | } | |||
402 | ||||
403 | if (PySequence_Size(op_flags_in) != nop) { | |||
404 | goto try_single_flags; | |||
405 | } | |||
406 | ||||
407 | for (iop = 0; iop < nop; ++iop) { | |||
408 | PyObject *f = PySequence_GetItem(op_flags_in, iop); | |||
409 | if (f == NULL((void*)0)) { | |||
410 | return 0; | |||
411 | } | |||
412 | /* If the first item is a string, try as one set of flags */ | |||
413 | if (iop == 0 && (PyBytes_Check(f)((((((PyObject*)(f))->ob_type))->tp_flags & ((1UL << 27))) != 0) || PyUnicode_Check(f)((((((PyObject*)(f))->ob_type))->tp_flags & ((1UL << 28))) != 0))) { | |||
414 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
415 | goto try_single_flags; | |||
416 | } | |||
417 | if (NpyIter_OpFlagsConverter(f, | |||
418 | &op_flags_array[iop]) != 1) { | |||
419 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
420 | return 0; | |||
421 | } | |||
422 | ||||
423 | Py_DECREF(f)_Py_DECREF(((PyObject*)(f))); | |||
424 | } | |||
425 | ||||
426 | return 1; | |||
427 | ||||
428 | try_single_flags: | |||
429 | if (NpyIter_OpFlagsConverter(op_flags_in, | |||
430 | &op_flags_array[0]) != 1) { | |||
431 | return 0; | |||
432 | } | |||
433 | ||||
434 | for (iop = 1; iop < nop; ++iop) { | |||
435 | op_flags_array[iop] = op_flags_array[0]; | |||
436 | } | |||
437 | ||||
438 | return 1; | |||
439 | } | |||
440 | ||||
441 | static int | |||
442 | npyiter_convert_dtypes(PyObject *op_dtypes_in, | |||
443 | PyArray_Descr **op_dtypes, | |||
444 | npy_intp nop) | |||
445 | { | |||
446 | npy_intp iop; | |||
447 | ||||
448 | /* | |||
449 | * If the input isn't a tuple of dtypes, try converting it as-is | |||
450 | * to a dtype, and replicating to all operands. | |||
451 | */ | |||
452 | if ((!PyTuple_Check(op_dtypes_in)((((((PyObject*)(op_dtypes_in))->ob_type))->tp_flags & ((1UL << 26))) != 0) && !PyList_Check(op_dtypes_in)((((((PyObject*)(op_dtypes_in))->ob_type))->tp_flags & ((1UL << 25))) != 0)) || | |||
453 | PySequence_Size(op_dtypes_in) != nop) { | |||
454 | goto try_single_dtype; | |||
455 | } | |||
456 | ||||
457 | for (iop = 0; iop < nop; ++iop) { | |||
458 | PyObject *dtype = PySequence_GetItem(op_dtypes_in, iop); | |||
459 | if (dtype == NULL((void*)0)) { | |||
460 | npy_intp i; | |||
461 | for (i = 0; i < iop; ++i ) { | |||
462 | Py_XDECREF(op_dtypes[i])_Py_XDECREF(((PyObject*)(op_dtypes[i]))); | |||
463 | } | |||
464 | return 0; | |||
465 | } | |||
466 | ||||
467 | /* Try converting the object to a descr */ | |||
468 | if (PyArray_DescrConverter2(dtype, &op_dtypes[iop]) != 1) { | |||
469 | npy_intp i; | |||
470 | for (i = 0; i < iop; ++i ) { | |||
471 | Py_XDECREF(op_dtypes[i])_Py_XDECREF(((PyObject*)(op_dtypes[i]))); | |||
472 | } | |||
473 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | |||
474 | PyErr_Clear(); | |||
475 | goto try_single_dtype; | |||
476 | } | |||
477 | ||||
478 | Py_DECREF(dtype)_Py_DECREF(((PyObject*)(dtype))); | |||
479 | } | |||
480 | ||||
481 | return 1; | |||
482 | ||||
483 | try_single_dtype: | |||
484 | if (PyArray_DescrConverter2(op_dtypes_in, &op_dtypes[0]) == 1) { | |||
485 | for (iop = 1; iop < nop; ++iop) { | |||
486 | op_dtypes[iop] = op_dtypes[0]; | |||
487 | Py_XINCREF(op_dtypes[iop])_Py_XINCREF(((PyObject*)(op_dtypes[iop]))); | |||
488 | } | |||
489 | return 1; | |||
490 | } | |||
491 | ||||
492 | return 0; | |||
493 | } | |||
494 | ||||
495 | static int | |||
496 | npyiter_convert_op_axes(PyObject *op_axes_in, int nop, | |||
497 | int **op_axes, int *oa_ndim) | |||
498 | { | |||
499 | PyObject *a; | |||
500 | int iop; | |||
501 | ||||
502 | if ((!PyTuple_Check(op_axes_in)((((((PyObject*)(op_axes_in))->ob_type))->tp_flags & ((1UL << 26))) != 0) && !PyList_Check(op_axes_in)((((((PyObject*)(op_axes_in))->ob_type))->tp_flags & ((1UL << 25))) != 0)) || | |||
503 | PySequence_Size(op_axes_in) != nop) { | |||
504 | PyErr_SetString(PyExc_ValueError, | |||
505 | "op_axes must be a tuple/list matching the number of ops"); | |||
506 | return 0; | |||
507 | } | |||
508 | ||||
509 | *oa_ndim = -1; | |||
510 | ||||
511 | /* Copy the tuples into op_axes */ | |||
512 | for (iop = 0; iop < nop; ++iop) { | |||
513 | int idim; | |||
514 | a = PySequence_GetItem(op_axes_in, iop); | |||
515 | if (a == NULL((void*)0)) { | |||
516 | return 0; | |||
517 | } | |||
518 | if (a == Py_None(&_Py_NoneStruct)) { | |||
519 | op_axes[iop] = NULL((void*)0); | |||
520 | } else { | |||
521 | if (!PyTuple_Check(a)((((((PyObject*)(a))->ob_type))->tp_flags & ((1UL << 26))) != 0) && !PyList_Check(a)((((((PyObject*)(a))->ob_type))->tp_flags & ((1UL << 25))) != 0)) { | |||
522 | PyErr_SetString(PyExc_ValueError, | |||
523 | "Each entry of op_axes must be None " | |||
524 | "or a tuple/list"); | |||
525 | Py_DECREF(a)_Py_DECREF(((PyObject*)(a))); | |||
526 | return 0; | |||
527 | } | |||
528 | if (*oa_ndim == -1) { | |||
529 | *oa_ndim = PySequence_Size(a); | |||
530 | if (*oa_ndim > NPY_MAXDIMS32) { | |||
531 | PyErr_SetString(PyExc_ValueError, | |||
532 | "Too many dimensions in op_axes"); | |||
533 | Py_DECREF(a)_Py_DECREF(((PyObject*)(a))); | |||
534 | return 0; | |||
535 | } | |||
536 | } | |||
537 | if (PySequence_Size(a) != *oa_ndim) { | |||
538 | PyErr_SetString(PyExc_ValueError, | |||
539 | "Each entry of op_axes must have the same size"); | |||
540 | Py_DECREF(a)_Py_DECREF(((PyObject*)(a))); | |||
541 | return 0; | |||
542 | } | |||
543 | for (idim = 0; idim < *oa_ndim; ++idim) { | |||
544 | PyObject *v = PySequence_GetItem(a, idim); | |||
545 | if (v == NULL((void*)0)) { | |||
546 | Py_DECREF(a)_Py_DECREF(((PyObject*)(a))); | |||
547 | return 0; | |||
548 | } | |||
549 | /* numpy.newaxis is None */ | |||
550 | if (v == Py_None(&_Py_NoneStruct)) { | |||
551 | op_axes[iop][idim] = -1; | |||
552 | } | |||
553 | else { | |||
554 | op_axes[iop][idim] = PyArray_PyIntAsInt(v); | |||
555 | if (op_axes[iop][idim]==-1 && | |||
556 | PyErr_Occurred()) { | |||
557 | Py_DECREF(a)_Py_DECREF(((PyObject*)(a))); | |||
558 | Py_DECREF(v)_Py_DECREF(((PyObject*)(v))); | |||
559 | return 0; | |||
560 | } | |||
561 | } | |||
562 | Py_DECREF(v)_Py_DECREF(((PyObject*)(v))); | |||
563 | } | |||
564 | } | |||
565 | Py_DECREF(a)_Py_DECREF(((PyObject*)(a))); | |||
566 | } | |||
567 | ||||
568 | if (*oa_ndim == -1) { | |||
569 | PyErr_SetString(PyExc_ValueError, | |||
570 | "If op_axes is provided, at least one list of axes " | |||
571 | "must be contained within it"); | |||
572 | return 0; | |||
573 | } | |||
574 | ||||
575 | return 1; | |||
576 | } | |||
577 | ||||
578 | /* | |||
579 | * Converts the operand array and op_flags array into the form | |||
580 | * NpyIter_AdvancedNew needs. Sets nop, and on success, each | |||
581 | * op[i] owns a reference to an array object. | |||
582 | */ | |||
583 | static int | |||
584 | npyiter_convert_ops(PyObject *op_in, PyObject *op_flags_in, | |||
585 | PyArrayObject **op, npy_uint32 *op_flags, | |||
586 | int *nop_out) | |||
587 | { | |||
588 | int iop, nop; | |||
589 | ||||
590 | /* nop and op */ | |||
591 | if (PyTuple_Check(op_in)((((((PyObject*)(op_in))->ob_type))->tp_flags & ((1UL << 26))) != 0) || PyList_Check(op_in)((((((PyObject*)(op_in))->ob_type))->tp_flags & ((1UL << 25))) != 0)) { | |||
592 | nop = PySequence_Size(op_in); | |||
593 | if (nop == 0) { | |||
594 | PyErr_SetString(PyExc_ValueError, | |||
595 | "Must provide at least one operand"); | |||
596 | return 0; | |||
597 | } | |||
598 | if (nop > NPY_MAXARGS32) { | |||
599 | PyErr_SetString(PyExc_ValueError, "Too many operands"); | |||
600 | return 0; | |||
601 | } | |||
602 | ||||
603 | for (iop = 0; iop < nop; ++iop) { | |||
604 | PyObject *item = PySequence_GetItem(op_in, iop); | |||
605 | if (item == NULL((void*)0)) { | |||
606 | npy_intp i; | |||
607 | for (i = 0; i < iop; ++i) { | |||
608 | Py_XDECREF(op[i])_Py_XDECREF(((PyObject*)(op[i]))); | |||
609 | } | |||
610 | return 0; | |||
611 | } | |||
612 | else if (item == Py_None(&_Py_NoneStruct)) { | |||
613 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
614 | item = NULL((void*)0); | |||
615 | } | |||
616 | /* This is converted to an array after op flags are retrieved */ | |||
617 | op[iop] = (PyArrayObject *)item; | |||
618 | } | |||
619 | } | |||
620 | else { | |||
621 | nop = 1; | |||
622 | /* Is converted to an array after op flags are retrieved */ | |||
623 | Py_INCREF(op_in)_Py_INCREF(((PyObject*)(op_in))); | |||
624 | op[0] = (PyArrayObject *)op_in; | |||
625 | } | |||
626 | ||||
627 | *nop_out = nop; | |||
628 | ||||
629 | /* op_flags */ | |||
630 | if (op_flags_in == NULL((void*)0) || op_flags_in == Py_None(&_Py_NoneStruct)) { | |||
631 | for (iop = 0; iop < nop; ++iop) { | |||
632 | /* | |||
633 | * By default, make NULL operands writeonly and flagged for | |||
634 | * allocation, and everything else readonly. To write | |||
635 | * to a provided operand, you must specify the write flag manually. | |||
636 | */ | |||
637 | if (op[iop] == NULL((void*)0)) { | |||
638 | op_flags[iop] = NPY_ITER_WRITEONLY0x00040000 | NPY_ITER_ALLOCATE0x01000000; | |||
639 | } | |||
640 | else { | |||
641 | op_flags[iop] = NPY_ITER_READONLY0x00020000; | |||
642 | } | |||
643 | } | |||
644 | } | |||
645 | else if (npyiter_convert_op_flags_array(op_flags_in, | |||
646 | op_flags, nop) != 1) { | |||
647 | for (iop = 0; iop < nop; ++iop) { | |||
648 | Py_XDECREF(op[iop])_Py_XDECREF(((PyObject*)(op[iop]))); | |||
649 | } | |||
650 | *nop_out = 0; | |||
651 | return 0; | |||
652 | } | |||
653 | ||||
654 | /* Now that we have the flags - convert all the ops to arrays */ | |||
655 | for (iop = 0; iop < nop; ++iop) { | |||
656 | if (op[iop] != NULL((void*)0)) { | |||
657 | PyArrayObject *ao; | |||
658 | int fromanyflags = 0; | |||
659 | ||||
660 | if (op_flags[iop]&(NPY_ITER_READWRITE0x00010000|NPY_ITER_WRITEONLY0x00040000)) { | |||
661 | fromanyflags |= NPY_ARRAY_WRITEBACKIFCOPY0x2000; | |||
662 | } | |||
663 | ao = (PyArrayObject *)PyArray_FROM_OF((PyObject *)op[iop],PyArray_CheckFromAny((PyObject *)op[iop], ((void*)0), 0, 0, fromanyflags , ((void*)0)) | |||
664 | fromanyflags)PyArray_CheckFromAny((PyObject *)op[iop], ((void*)0), 0, 0, fromanyflags , ((void*)0)); | |||
665 | if (ao == NULL((void*)0)) { | |||
666 | if (PyErr_Occurred() && | |||
667 | PyErr_ExceptionMatches(PyExc_TypeError)) { | |||
668 | PyErr_SetString(PyExc_TypeError, | |||
669 | "Iterator operand is flagged as writeable, " | |||
670 | "but is an object which cannot be written " | |||
671 | "back to via WRITEBACKIFCOPY"); | |||
672 | } | |||
673 | for (iop = 0; iop < nop; ++iop) { | |||
674 | Py_DECREF(op[iop])_Py_DECREF(((PyObject*)(op[iop]))); | |||
675 | } | |||
676 | *nop_out = 0; | |||
677 | return 0; | |||
678 | } | |||
679 | Py_DECREF(op[iop])_Py_DECREF(((PyObject*)(op[iop]))); | |||
680 | op[iop] = ao; | |||
681 | } | |||
682 | } | |||
683 | ||||
684 | return 1; | |||
685 | } | |||
686 | ||||
687 | static int | |||
688 | npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds) | |||
689 | { | |||
690 | static char *kwlist[] = {"op", "flags", "op_flags", "op_dtypes", | |||
691 | "order", "casting", "op_axes", "itershape", | |||
692 | "buffersize", | |||
693 | NULL((void*)0)}; | |||
694 | ||||
695 | PyObject *op_in = NULL((void*)0), *op_flags_in = NULL((void*)0), | |||
696 | *op_dtypes_in = NULL((void*)0), *op_axes_in = NULL((void*)0); | |||
697 | ||||
698 | int iop, nop = 0; | |||
699 | PyArrayObject *op[NPY_MAXARGS32]; | |||
700 | npy_uint32 flags = 0; | |||
701 | NPY_ORDER order = NPY_KEEPORDER; | |||
702 | NPY_CASTING casting = NPY_SAFE_CASTING; | |||
703 | npy_uint32 op_flags[NPY_MAXARGS32]; | |||
704 | PyArray_Descr *op_request_dtypes[NPY_MAXARGS32]; | |||
705 | int oa_ndim = -1; | |||
706 | int op_axes_arrays[NPY_MAXARGS32][NPY_MAXDIMS32]; | |||
707 | int *op_axes[NPY_MAXARGS32]; | |||
708 | PyArray_Dims itershape = {NULL((void*)0), -1}; | |||
709 | int buffersize = 0; | |||
710 | ||||
711 | if (self->iter != NULL((void*)0)) { | |||
712 | PyErr_SetString(PyExc_ValueError, | |||
713 | "Iterator was already initialized"); | |||
714 | return -1; | |||
715 | } | |||
716 | ||||
717 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, kwds, "O|O&OOO&O&OO&i:nditer", kwlist, | |||
718 | &op_in, | |||
719 | NpyIter_GlobalFlagsConverter, &flags, | |||
720 | &op_flags_in, | |||
721 | &op_dtypes_in, | |||
722 | PyArray_OrderConverter, &order, | |||
723 | PyArray_CastingConverter, &casting, | |||
724 | &op_axes_in, | |||
725 | PyArray_OptionalIntpConverter, &itershape, | |||
726 | &buffersize)) { | |||
727 | npy_free_cache_dim_obj(itershape); | |||
728 | return -1; | |||
729 | } | |||
730 | ||||
731 | /* Set the dtypes and ops to all NULL to start */ | |||
732 | memset(op_request_dtypes, 0, sizeof(op_request_dtypes)); | |||
733 | ||||
734 | /* op and op_flags */ | |||
735 | if (npyiter_convert_ops(op_in, op_flags_in, op, op_flags, &nop) | |||
736 | != 1) { | |||
737 | goto fail; | |||
738 | } | |||
739 | ||||
740 | /* op_request_dtypes */ | |||
741 | if (op_dtypes_in != NULL((void*)0) && op_dtypes_in != Py_None(&_Py_NoneStruct) && | |||
742 | npyiter_convert_dtypes(op_dtypes_in, | |||
743 | op_request_dtypes, nop) != 1) { | |||
744 | goto fail; | |||
745 | } | |||
746 | ||||
747 | /* op_axes */ | |||
748 | if (op_axes_in != NULL((void*)0) && op_axes_in != Py_None(&_Py_NoneStruct)) { | |||
749 | /* Initialize to point to the op_axes arrays */ | |||
750 | for (iop = 0; iop < nop; ++iop) { | |||
751 | op_axes[iop] = op_axes_arrays[iop]; | |||
752 | } | |||
753 | ||||
754 | if (npyiter_convert_op_axes(op_axes_in, nop, | |||
755 | op_axes, &oa_ndim) != 1) { | |||
756 | goto fail; | |||
757 | } | |||
758 | } | |||
759 | ||||
760 | if (itershape.len != -1) { | |||
761 | if (oa_ndim == -1) { | |||
762 | oa_ndim = itershape.len; | |||
763 | memset(op_axes, 0, sizeof(op_axes[0]) * nop); | |||
764 | } | |||
765 | else if (oa_ndim != itershape.len) { | |||
766 | PyErr_SetString(PyExc_ValueError, | |||
767 | "'op_axes' and 'itershape' must have the same number " | |||
768 | "of entries equal to the iterator ndim"); | |||
769 | goto fail; | |||
770 | } | |||
771 | } | |||
772 | ||||
773 | self->iter = NpyIter_AdvancedNew(nop, op, flags, order, casting, op_flags, | |||
774 | op_request_dtypes, | |||
775 | oa_ndim, oa_ndim >= 0 ? op_axes : NULL((void*)0), | |||
776 | itershape.ptr, | |||
777 | buffersize); | |||
778 | ||||
779 | if (self->iter == NULL((void*)0)) { | |||
780 | goto fail; | |||
781 | } | |||
782 | ||||
783 | /* Cache some values for the member functions to use */ | |||
784 | if (npyiter_cache_values(self) < 0) { | |||
785 | goto fail; | |||
786 | } | |||
787 | ||||
788 | if (NpyIter_GetIterSize(self->iter) == 0) { | |||
789 | self->started = 1; | |||
790 | self->finished = 1; | |||
791 | } | |||
792 | else { | |||
793 | self->started = 0; | |||
794 | self->finished = 0; | |||
795 | } | |||
796 | ||||
797 | npy_free_cache_dim_obj(itershape); | |||
798 | ||||
799 | /* Release the references we got to the ops and dtypes */ | |||
800 | for (iop = 0; iop < nop; ++iop) { | |||
801 | Py_XDECREF(op[iop])_Py_XDECREF(((PyObject*)(op[iop]))); | |||
802 | Py_XDECREF(op_request_dtypes[iop])_Py_XDECREF(((PyObject*)(op_request_dtypes[iop]))); | |||
803 | } | |||
804 | ||||
805 | return 0; | |||
806 | ||||
807 | fail: | |||
808 | npy_free_cache_dim_obj(itershape); | |||
809 | for (iop = 0; iop < nop; ++iop) { | |||
810 | Py_XDECREF(op[iop])_Py_XDECREF(((PyObject*)(op[iop]))); | |||
811 | Py_XDECREF(op_request_dtypes[iop])_Py_XDECREF(((PyObject*)(op_request_dtypes[iop]))); | |||
812 | } | |||
813 | return -1; | |||
814 | } | |||
815 | ||||
816 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | |||
817 | NpyIter_NestedIters(PyObject *NPY_UNUSED(self)(__NPY_UNUSED_TAGGEDself) __attribute__ ((__unused__)), | |||
818 | PyObject *args, PyObject *kwds) | |||
819 | { | |||
820 | static char *kwlist[] = {"op", "axes", "flags", "op_flags", | |||
821 | "op_dtypes", "order", | |||
822 | "casting", "buffersize", | |||
823 | NULL((void*)0)}; | |||
824 | ||||
825 | PyObject *op_in = NULL((void*)0), *axes_in = NULL((void*)0), | |||
826 | *op_flags_in = NULL((void*)0), *op_dtypes_in = NULL((void*)0); | |||
827 | ||||
828 | int iop, nop = 0, inest, nnest = 0; | |||
829 | PyArrayObject *op[NPY_MAXARGS32]; | |||
830 | npy_uint32 flags = 0, flags_inner; | |||
831 | NPY_ORDER order = NPY_KEEPORDER; | |||
832 | NPY_CASTING casting = NPY_SAFE_CASTING; | |||
833 | npy_uint32 op_flags[NPY_MAXARGS32], op_flags_inner[NPY_MAXARGS32]; | |||
834 | PyArray_Descr *op_request_dtypes[NPY_MAXARGS32], | |||
835 | *op_request_dtypes_inner[NPY_MAXARGS32]; | |||
836 | int op_axes_data[NPY_MAXDIMS32]; | |||
837 | int *nested_op_axes[NPY_MAXDIMS32]; | |||
838 | int nested_naxes[NPY_MAXDIMS32], iaxes, naxes; | |||
839 | int negones[NPY_MAXDIMS32]; | |||
840 | char used_axes[NPY_MAXDIMS32]; | |||
841 | int buffersize = 0; | |||
842 | ||||
843 | PyObject *ret = NULL((void*)0); | |||
844 | ||||
845 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, kwds, "OO|O&OOO&O&i", kwlist, | |||
846 | &op_in, | |||
847 | &axes_in, | |||
848 | NpyIter_GlobalFlagsConverter, &flags, | |||
849 | &op_flags_in, | |||
850 | &op_dtypes_in, | |||
851 | PyArray_OrderConverter, &order, | |||
852 | PyArray_CastingConverter, &casting, | |||
853 | &buffersize)) { | |||
854 | return NULL((void*)0); | |||
855 | } | |||
856 | ||||
857 | /* axes */ | |||
858 | if (!PyTuple_Check(axes_in)((((((PyObject*)(axes_in))->ob_type))->tp_flags & ( (1UL << 26))) != 0) && !PyList_Check(axes_in)((((((PyObject*)(axes_in))->ob_type))->tp_flags & ( (1UL << 25))) != 0)) { | |||
859 | PyErr_SetString(PyExc_ValueError, | |||
860 | "axes must be a tuple of axis arrays"); | |||
861 | return NULL((void*)0); | |||
862 | } | |||
863 | nnest = PySequence_Size(axes_in); | |||
864 | if (nnest < 2) { | |||
865 | PyErr_SetString(PyExc_ValueError, | |||
866 | "axes must have at least 2 entries for nested iteration"); | |||
867 | return NULL((void*)0); | |||
868 | } | |||
869 | naxes = 0; | |||
870 | memset(used_axes, 0, NPY_MAXDIMS32); | |||
871 | for (inest = 0; inest < nnest; ++inest) { | |||
872 | PyObject *item = PySequence_GetItem(axes_in, inest); | |||
873 | npy_intp i; | |||
874 | if (item == NULL((void*)0)) { | |||
875 | return NULL((void*)0); | |||
876 | } | |||
877 | if (!PyTuple_Check(item)((((((PyObject*)(item))->ob_type))->tp_flags & ((1UL << 26))) != 0) && !PyList_Check(item)((((((PyObject*)(item))->ob_type))->tp_flags & ((1UL << 25))) != 0)) { | |||
878 | PyErr_SetString(PyExc_ValueError, | |||
879 | "Each item in axes must be a an integer tuple"); | |||
880 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
881 | return NULL((void*)0); | |||
882 | } | |||
883 | nested_naxes[inest] = PySequence_Size(item); | |||
884 | if (naxes + nested_naxes[inest] > NPY_MAXDIMS32) { | |||
885 | PyErr_SetString(PyExc_ValueError, | |||
886 | "Too many axes given"); | |||
887 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
888 | return NULL((void*)0); | |||
889 | } | |||
890 | for (i = 0; i < nested_naxes[inest]; ++i) { | |||
891 | PyObject *v = PySequence_GetItem(item, i); | |||
892 | npy_intp axis; | |||
893 | if (v == NULL((void*)0)) { | |||
894 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
895 | return NULL((void*)0); | |||
896 | } | |||
897 | axis = PyLong_AsLong(v); | |||
898 | Py_DECREF(v)_Py_DECREF(((PyObject*)(v))); | |||
899 | if (axis < 0 || axis >= NPY_MAXDIMS32) { | |||
900 | PyErr_SetString(PyExc_ValueError, | |||
901 | "An axis is out of bounds"); | |||
902 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
903 | return NULL((void*)0); | |||
904 | } | |||
905 | /* | |||
906 | * This check is very important, without it out of bounds | |||
907 | * data accesses are possible. | |||
908 | */ | |||
909 | if (used_axes[axis] != 0) { | |||
910 | PyErr_SetString(PyExc_ValueError, | |||
911 | "An axis is used more than once"); | |||
912 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
913 | return NULL((void*)0); | |||
914 | } | |||
915 | used_axes[axis] = 1; | |||
916 | op_axes_data[naxes+i] = axis; | |||
917 | } | |||
918 | nested_op_axes[inest] = &op_axes_data[naxes]; | |||
919 | naxes += nested_naxes[inest]; | |||
920 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
921 | } | |||
922 | ||||
923 | /* op and op_flags */ | |||
924 | if (npyiter_convert_ops(op_in, op_flags_in, op, op_flags, &nop) | |||
925 | != 1) { | |||
926 | return NULL((void*)0); | |||
927 | } | |||
928 | ||||
929 | /* Set the dtypes to all NULL to start as well */ | |||
930 | memset(op_request_dtypes, 0, sizeof(op_request_dtypes[0])*nop); | |||
931 | memset(op_request_dtypes_inner, 0, | |||
932 | sizeof(op_request_dtypes_inner[0])*nop); | |||
933 | ||||
934 | /* op_request_dtypes */ | |||
935 | if (op_dtypes_in != NULL((void*)0) && op_dtypes_in != Py_None(&_Py_NoneStruct) && | |||
936 | npyiter_convert_dtypes(op_dtypes_in, | |||
937 | op_request_dtypes, nop) != 1) { | |||
938 | goto fail; | |||
939 | } | |||
940 | ||||
941 | ret = PyTuple_New(nnest); | |||
942 | if (ret == NULL((void*)0)) { | |||
943 | goto fail; | |||
944 | } | |||
945 | ||||
946 | /* For broadcasting allocated arrays */ | |||
947 | for (iaxes = 0; iaxes < naxes; ++iaxes) { | |||
948 | negones[iaxes] = -1; | |||
949 | } | |||
950 | ||||
951 | /* | |||
952 | * Clear any unnecessary ALLOCATE flags, so we can use them | |||
953 | * to indicate exactly the allocated outputs. Also, separate | |||
954 | * the inner loop flags. | |||
955 | */ | |||
956 | for (iop = 0; iop < nop; ++iop) { | |||
957 | if ((op_flags[iop]&NPY_ITER_ALLOCATE0x01000000) && op[iop] != NULL((void*)0)) { | |||
958 | op_flags[iop] &= ~NPY_ITER_ALLOCATE0x01000000; | |||
959 | } | |||
960 | ||||
961 | /* | |||
962 | * Clear any flags allowing copies or output allocation for | |||
963 | * the inner loop. | |||
964 | */ | |||
965 | op_flags_inner[iop] = op_flags[iop] & ~(NPY_ITER_COPY0x00400000| | |||
966 | NPY_ITER_UPDATEIFCOPY0x00800000| | |||
967 | NPY_ITER_ALLOCATE0x01000000); | |||
968 | /* | |||
969 | * If buffering is enabled and copying is not, | |||
970 | * clear the nbo_aligned flag and strip the data type | |||
971 | * for the outer loops. | |||
972 | */ | |||
973 | if ((flags&(NPY_ITER_BUFFERED0x00000200)) && | |||
974 | !(op_flags[iop]&(NPY_ITER_COPY0x00400000| | |||
975 | NPY_ITER_UPDATEIFCOPY0x00800000| | |||
976 | NPY_ITER_ALLOCATE0x01000000))) { | |||
977 | op_flags[iop] &= ~(NPY_ITER_NBO0x00080000|NPY_ITER_ALIGNED0x00100000|NPY_ITER_CONTIG0x00200000); | |||
978 | op_request_dtypes_inner[iop] = op_request_dtypes[iop]; | |||
979 | op_request_dtypes[iop] = NULL((void*)0); | |||
980 | } | |||
981 | } | |||
982 | ||||
983 | /* Only the inner loop gets the buffering and no inner flags */ | |||
984 | flags_inner = flags&~NPY_ITER_COMMON_DTYPE0x00000010; | |||
985 | flags &= ~(NPY_ITER_EXTERNAL_LOOP0x00000008| | |||
986 | NPY_ITER_BUFFERED0x00000200); | |||
987 | ||||
988 | for (inest = 0; inest < nnest; ++inest) { | |||
989 | NewNpyArrayIterObject *iter; | |||
990 | int *op_axes_nop[NPY_MAXARGS32]; | |||
991 | ||||
992 | /* | |||
993 | * All the operands' op_axes are the same, except for | |||
994 | * allocated outputs. | |||
995 | */ | |||
996 | for (iop = 0; iop < nop; ++iop) { | |||
997 | if (op_flags[iop]&NPY_ITER_ALLOCATE0x01000000) { | |||
998 | if (inest == 0) { | |||
999 | op_axes_nop[iop] = NULL((void*)0); | |||
1000 | } | |||
1001 | else { | |||
1002 | op_axes_nop[iop] = negones; | |||
1003 | } | |||
1004 | } | |||
1005 | else { | |||
1006 | op_axes_nop[iop] = nested_op_axes[inest]; | |||
1007 | } | |||
1008 | } | |||
1009 | ||||
1010 | /* | |||
1011 | printf("\n"); | |||
1012 | for (iop = 0; iop < nop; ++iop) { | |||
1013 | npy_intp i; | |||
1014 | ||||
1015 | for (i = 0; i < nested_naxes[inest]; ++i) { | |||
1016 | printf("%d ", (int)op_axes_nop[iop][i]); | |||
1017 | } | |||
1018 | printf("\n"); | |||
1019 | } | |||
1020 | */ | |||
1021 | ||||
1022 | /* Allocate the iterator */ | |||
1023 | iter = (NewNpyArrayIterObject *)npyiter_new(&NpyIter_Type, NULL((void*)0), NULL((void*)0)); | |||
1024 | if (iter == NULL((void*)0)) { | |||
1025 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
1026 | goto fail; | |||
1027 | } | |||
1028 | ||||
1029 | if (inest < nnest-1) { | |||
1030 | iter->iter = NpyIter_AdvancedNew(nop, op, flags, order, | |||
1031 | casting, op_flags, op_request_dtypes, | |||
1032 | nested_naxes[inest], op_axes_nop, | |||
1033 | NULL((void*)0), | |||
1034 | 0); | |||
1035 | } | |||
1036 | else { | |||
1037 | iter->iter = NpyIter_AdvancedNew(nop, op, flags_inner, order, | |||
1038 | casting, op_flags_inner, | |||
1039 | op_request_dtypes_inner, | |||
1040 | nested_naxes[inest], op_axes_nop, | |||
1041 | NULL((void*)0), | |||
1042 | buffersize); | |||
1043 | } | |||
1044 | ||||
1045 | if (iter->iter == NULL((void*)0)) { | |||
1046 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
1047 | goto fail; | |||
1048 | } | |||
1049 | ||||
1050 | /* Cache some values for the member functions to use */ | |||
1051 | if (npyiter_cache_values(iter) < 0) { | |||
1052 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
1053 | goto fail; | |||
1054 | } | |||
1055 | ||||
1056 | if (NpyIter_GetIterSize(iter->iter) == 0) { | |||
1057 | iter->started = 1; | |||
1058 | iter->finished = 1; | |||
1059 | } | |||
1060 | else { | |||
1061 | iter->started = 0; | |||
1062 | iter->finished = 0; | |||
1063 | } | |||
1064 | ||||
1065 | /* | |||
1066 | * If there are any allocated outputs or any copies were made, | |||
1067 | * adjust op so that the other iterators use the same ones. | |||
1068 | */ | |||
1069 | if (inest == 0) { | |||
1070 | PyArrayObject **operands = NpyIter_GetOperandArray(iter->iter); | |||
1071 | for (iop = 0; iop < nop; ++iop) { | |||
1072 | if (op[iop] != operands[iop]) { | |||
1073 | Py_XDECREF(op[iop])_Py_XDECREF(((PyObject*)(op[iop]))); | |||
1074 | op[iop] = operands[iop]; | |||
1075 | Py_INCREF(op[iop])_Py_INCREF(((PyObject*)(op[iop]))); | |||
1076 | } | |||
1077 | ||||
1078 | /* | |||
1079 | * Clear any flags allowing copies for | |||
1080 | * the rest of the iterators | |||
1081 | */ | |||
1082 | op_flags[iop] &= ~(NPY_ITER_COPY0x00400000| | |||
1083 | NPY_ITER_UPDATEIFCOPY0x00800000); | |||
1084 | } | |||
1085 | /* Clear the common dtype flag for the rest of the iterators */ | |||
1086 | flags &= ~NPY_ITER_COMMON_DTYPE0x00000010; | |||
1087 | } | |||
1088 | ||||
1089 | PyTuple_SET_ITEM(ret, inest, (PyObject *)iter)PyTuple_SetItem(ret, inest, (PyObject *)iter); | |||
1090 | } | |||
1091 | ||||
1092 | /* Release our references to the ops and dtypes */ | |||
1093 | for (iop = 0; iop < nop; ++iop) { | |||
1094 | Py_XDECREF(op[iop])_Py_XDECREF(((PyObject*)(op[iop]))); | |||
1095 | Py_XDECREF(op_request_dtypes[iop])_Py_XDECREF(((PyObject*)(op_request_dtypes[iop]))); | |||
1096 | Py_XDECREF(op_request_dtypes_inner[iop])_Py_XDECREF(((PyObject*)(op_request_dtypes_inner[iop]))); | |||
1097 | } | |||
1098 | ||||
1099 | /* Set up the nested child references */ | |||
1100 | for (inest = 0; inest < nnest-1; ++inest) { | |||
1101 | NewNpyArrayIterObject *iter; | |||
1102 | iter = (NewNpyArrayIterObject *)PyTuple_GET_ITEM(ret, inest)((((void) (0)), (PyTupleObject *)(ret))->ob_item[inest]); | |||
1103 | /* | |||
1104 | * Indicates which iterator to reset with new base pointers | |||
1105 | * each iteration step. | |||
1106 | */ | |||
1107 | iter->nested_child = | |||
1108 | (NewNpyArrayIterObject *)PyTuple_GET_ITEM(ret, inest+1)((((void) (0)), (PyTupleObject *)(ret))->ob_item[inest+1]); | |||
1109 | Py_INCREF(iter->nested_child)_Py_INCREF(((PyObject*)(iter->nested_child))); | |||
1110 | /* | |||
1111 | * Need to do a nested reset so all the iterators point | |||
1112 | * at the right data | |||
1113 | */ | |||
1114 | if (NpyIter_ResetBasePointers(iter->nested_child->iter, | |||
1115 | iter->dataptrs, NULL((void*)0)) != NPY_SUCCEED1) { | |||
1116 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
1117 | return NULL((void*)0); | |||
1118 | } | |||
1119 | } | |||
1120 | ||||
1121 | return ret; | |||
1122 | ||||
1123 | fail: | |||
1124 | for (iop = 0; iop < nop; ++iop) { | |||
1125 | Py_XDECREF(op[iop])_Py_XDECREF(((PyObject*)(op[iop]))); | |||
1126 | Py_XDECREF(op_request_dtypes[iop])_Py_XDECREF(((PyObject*)(op_request_dtypes[iop]))); | |||
1127 | Py_XDECREF(op_request_dtypes_inner[iop])_Py_XDECREF(((PyObject*)(op_request_dtypes_inner[iop]))); | |||
1128 | } | |||
1129 | return NULL((void*)0); | |||
1130 | } | |||
1131 | ||||
1132 | ||||
1133 | static void | |||
1134 | npyiter_dealloc(NewNpyArrayIterObject *self) | |||
1135 | { | |||
1136 | if (self->iter) { | |||
1137 | /* Store error, so that WriteUnraisable cannot clear an existing one */ | |||
1138 | PyObject *exc, *val, *tb; | |||
1139 | PyErr_Fetch(&exc, &val, &tb); | |||
1140 | if (npyiter_has_writeback(self->iter)) { | |||
1141 | if (PyErr_WarnEx(PyExc_RuntimeWarning, | |||
1142 | "Temporary data has not been written back to one of the " | |||
1143 | "operands. Typically nditer is used as a context manager " | |||
1144 | "otherwise 'close' must be called before reading iteration " | |||
1145 | "results.", 1) < 0) { | |||
1146 | PyObject *s; | |||
1147 | ||||
1148 | s = PyUnicode_FromString("npyiter_dealloc"); | |||
1149 | if (s) { | |||
1150 | PyErr_WriteUnraisable(s); | |||
1151 | Py_DECREF(s)_Py_DECREF(((PyObject*)(s))); | |||
1152 | } | |||
1153 | else { | |||
1154 | PyErr_WriteUnraisable(Py_None(&_Py_NoneStruct)); | |||
1155 | } | |||
1156 | } | |||
1157 | } | |||
1158 | if (!NpyIter_Deallocate(self->iter)) { | |||
1159 | PyErr_WriteUnraisable(Py_None(&_Py_NoneStruct)); | |||
1160 | } | |||
1161 | self->iter = NULL((void*)0); | |||
1162 | Py_XDECREF(self->nested_child)_Py_XDECREF(((PyObject*)(self->nested_child))); | |||
1163 | self->nested_child = NULL((void*)0); | |||
1164 | PyErr_Restore(exc, val, tb); | |||
1165 | } | |||
1166 | Py_TYPE(self)(((PyObject*)(self))->ob_type)->tp_free((PyObject*)self); | |||
1167 | } | |||
1168 | ||||
1169 | static int | |||
1170 | npyiter_resetbasepointers(NewNpyArrayIterObject *self) | |||
1171 | { | |||
1172 | while (self->nested_child) { | |||
1173 | if (NpyIter_ResetBasePointers(self->nested_child->iter, | |||
1174 | self->dataptrs, NULL((void*)0)) != NPY_SUCCEED1) { | |||
1175 | return NPY_FAIL0; | |||
1176 | } | |||
1177 | self = self->nested_child; | |||
1178 | if (NpyIter_GetIterSize(self->iter) == 0) { | |||
1179 | self->started = 1; | |||
1180 | self->finished = 1; | |||
1181 | } | |||
1182 | else { | |||
1183 | self->started = 0; | |||
1184 | self->finished = 0; | |||
1185 | } | |||
1186 | } | |||
1187 | ||||
1188 | return NPY_SUCCEED1; | |||
1189 | } | |||
1190 | ||||
1191 | static PyObject * | |||
1192 | npyiter_reset(NewNpyArrayIterObject *self) | |||
1193 | { | |||
1194 | if (self->iter == NULL((void*)0)) { | |||
1195 | PyErr_SetString(PyExc_ValueError, | |||
1196 | "Iterator is invalid"); | |||
1197 | return NULL((void*)0); | |||
1198 | } | |||
1199 | ||||
1200 | if (NpyIter_Reset(self->iter, NULL((void*)0)) != NPY_SUCCEED1) { | |||
1201 | return NULL((void*)0); | |||
1202 | } | |||
1203 | if (NpyIter_GetIterSize(self->iter) == 0) { | |||
1204 | self->started = 1; | |||
1205 | self->finished = 1; | |||
1206 | } | |||
1207 | else { | |||
1208 | self->started = 0; | |||
1209 | self->finished = 0; | |||
1210 | } | |||
1211 | ||||
1212 | if (self->get_multi_index == NULL((void*)0) && NpyIter_HasMultiIndex(self->iter)) { | |||
1213 | self->get_multi_index = NpyIter_GetGetMultiIndex(self->iter, NULL((void*)0)); | |||
1214 | } | |||
1215 | ||||
1216 | /* If there is nesting, the nested iterators should be reset */ | |||
1217 | if (npyiter_resetbasepointers(self) != NPY_SUCCEED1) { | |||
1218 | return NULL((void*)0); | |||
1219 | } | |||
1220 | ||||
1221 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
1222 | } | |||
1223 | ||||
1224 | /* | |||
1225 | * Makes a copy of the iterator. Note that the nesting is not | |||
1226 | * copied. | |||
1227 | */ | |||
1228 | static PyObject * | |||
1229 | npyiter_copy(NewNpyArrayIterObject *self) | |||
1230 | { | |||
1231 | NewNpyArrayIterObject *iter; | |||
1232 | ||||
1233 | if (self->iter == NULL((void*)0)) { | |||
1234 | PyErr_SetString(PyExc_ValueError, | |||
1235 | "Iterator is invalid"); | |||
1236 | return NULL((void*)0); | |||
1237 | } | |||
1238 | ||||
1239 | /* Allocate the iterator */ | |||
1240 | iter = (NewNpyArrayIterObject *)npyiter_new(&NpyIter_Type, NULL((void*)0), NULL((void*)0)); | |||
1241 | if (iter == NULL((void*)0)) { | |||
1242 | return NULL((void*)0); | |||
1243 | } | |||
1244 | ||||
1245 | /* Copy the C iterator */ | |||
1246 | iter->iter = NpyIter_Copy(self->iter); | |||
1247 | if (iter->iter == NULL((void*)0)) { | |||
1248 | Py_DECREF(iter)_Py_DECREF(((PyObject*)(iter))); | |||
1249 | return NULL((void*)0); | |||
1250 | } | |||
1251 | ||||
1252 | /* Cache some values for the member functions to use */ | |||
1253 | if (npyiter_cache_values(iter) < 0) { | |||
1254 | Py_DECREF(iter)_Py_DECREF(((PyObject*)(iter))); | |||
1255 | return NULL((void*)0); | |||
1256 | } | |||
1257 | ||||
1258 | iter->started = self->started; | |||
1259 | iter->finished = self->finished; | |||
1260 | ||||
1261 | return (PyObject *)iter; | |||
1262 | } | |||
1263 | ||||
1264 | static PyObject * | |||
1265 | npyiter_iternext(NewNpyArrayIterObject *self) | |||
1266 | { | |||
1267 | if (self->iter != NULL((void*)0) && self->iternext != NULL((void*)0) && | |||
1268 | !self->finished && self->iternext(self->iter)) { | |||
1269 | /* If there is nesting, the nested iterators should be reset */ | |||
1270 | if (npyiter_resetbasepointers(self) != NPY_SUCCEED1) { | |||
1271 | return NULL((void*)0); | |||
1272 | } | |||
1273 | ||||
1274 | Py_RETURN_TRUEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct )))), ((PyObject *) &_Py_TrueStruct); | |||
1275 | } | |||
1276 | else { | |||
1277 | if (PyErr_Occurred()) { | |||
1278 | /* casting error, buffer cleanup will occur at reset or dealloc */ | |||
1279 | return NULL((void*)0); | |||
1280 | } | |||
1281 | self->finished = 1; | |||
1282 | Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct )))), ((PyObject *) &_Py_FalseStruct); | |||
1283 | } | |||
1284 | } | |||
1285 | ||||
1286 | static PyObject * | |||
1287 | npyiter_remove_axis(NewNpyArrayIterObject *self, PyObject *args) | |||
1288 | { | |||
1289 | int axis = 0; | |||
1290 | ||||
1291 | if (self->iter == NULL((void*)0)) { | |||
1292 | PyErr_SetString(PyExc_ValueError, | |||
1293 | "Iterator is invalid"); | |||
1294 | return NULL((void*)0); | |||
1295 | } | |||
1296 | ||||
1297 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "i:remove_axis", &axis)) { | |||
1298 | return NULL((void*)0); | |||
1299 | } | |||
1300 | ||||
1301 | if (NpyIter_RemoveAxis(self->iter, axis) != NPY_SUCCEED1) { | |||
1302 | return NULL((void*)0); | |||
1303 | } | |||
1304 | /* RemoveAxis invalidates cached values */ | |||
1305 | if (npyiter_cache_values(self) < 0) { | |||
1306 | return NULL((void*)0); | |||
1307 | } | |||
1308 | /* RemoveAxis also resets the iterator */ | |||
1309 | if (NpyIter_GetIterSize(self->iter) == 0) { | |||
1310 | self->started = 1; | |||
1311 | self->finished = 1; | |||
1312 | } | |||
1313 | else { | |||
1314 | self->started = 0; | |||
1315 | self->finished = 0; | |||
1316 | } | |||
1317 | ||||
1318 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
1319 | } | |||
1320 | ||||
1321 | static PyObject * | |||
1322 | npyiter_remove_multi_index(NewNpyArrayIterObject *self) | |||
1323 | { | |||
1324 | if (self->iter == NULL((void*)0)) { | |||
1325 | PyErr_SetString(PyExc_ValueError, | |||
1326 | "Iterator is invalid"); | |||
1327 | return NULL((void*)0); | |||
1328 | } | |||
1329 | ||||
1330 | NpyIter_RemoveMultiIndex(self->iter); | |||
1331 | /* RemoveMultiIndex invalidates cached values */ | |||
1332 | npyiter_cache_values(self); | |||
1333 | /* RemoveMultiIndex also resets the iterator */ | |||
1334 | if (NpyIter_GetIterSize(self->iter) == 0) { | |||
1335 | self->started = 1; | |||
1336 | self->finished = 1; | |||
1337 | } | |||
1338 | else { | |||
1339 | self->started = 0; | |||
1340 | self->finished = 0; | |||
1341 | } | |||
1342 | ||||
1343 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
1344 | } | |||
1345 | ||||
1346 | static PyObject * | |||
1347 | npyiter_enable_external_loop(NewNpyArrayIterObject *self) | |||
1348 | { | |||
1349 | if (self->iter == NULL((void*)0)) { | |||
1350 | PyErr_SetString(PyExc_ValueError, | |||
1351 | "Iterator is invalid"); | |||
1352 | return NULL((void*)0); | |||
1353 | } | |||
1354 | ||||
1355 | NpyIter_EnableExternalLoop(self->iter); | |||
1356 | /* EnableExternalLoop invalidates cached values */ | |||
1357 | npyiter_cache_values(self); | |||
1358 | /* EnableExternalLoop also resets the iterator */ | |||
1359 | if (NpyIter_GetIterSize(self->iter) == 0) { | |||
1360 | self->started = 1; | |||
1361 | self->finished = 1; | |||
1362 | } | |||
1363 | else { | |||
1364 | self->started = 0; | |||
1365 | self->finished = 0; | |||
1366 | } | |||
1367 | ||||
1368 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
1369 | } | |||
1370 | ||||
1371 | static PyObject * | |||
1372 | npyiter_debug_print(NewNpyArrayIterObject *self) | |||
1373 | { | |||
1374 | if (self->iter != NULL((void*)0)) { | |||
1375 | NpyIter_DebugPrint(self->iter); | |||
1376 | } | |||
1377 | else { | |||
1378 | printf("Iterator: (nil)\n")__printf_chk (2 - 1, "Iterator: (nil)\n"); | |||
1379 | } | |||
1380 | ||||
1381 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
1382 | } | |||
1383 | ||||
1384 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | |||
1385 | npyiter_seq_item(NewNpyArrayIterObject *self, Py_ssize_t i); | |||
1386 | ||||
1387 | static PyObject *npyiter_value_get(NewNpyArrayIterObject *self) | |||
1388 | { | |||
1389 | PyObject *ret; | |||
1390 | ||||
1391 | npy_intp iop, nop; | |||
1392 | ||||
1393 | if (self->iter == NULL((void*)0) || self->finished) { | |||
1394 | PyErr_SetString(PyExc_ValueError, | |||
1395 | "Iterator is past the end"); | |||
1396 | return NULL((void*)0); | |||
1397 | } | |||
1398 | ||||
1399 | nop = NpyIter_GetNOp(self->iter); | |||
1400 | ||||
1401 | /* Return an array or tuple of arrays with the values */ | |||
1402 | if (nop == 1) { | |||
1403 | ret = npyiter_seq_item(self, 0); | |||
1404 | } | |||
1405 | else { | |||
1406 | ret = PyTuple_New(nop); | |||
1407 | if (ret == NULL((void*)0)) { | |||
1408 | return NULL((void*)0); | |||
1409 | } | |||
1410 | for (iop = 0; iop < nop; ++iop) { | |||
1411 | PyObject *a = npyiter_seq_item(self, iop); | |||
1412 | if (a == NULL((void*)0)) { | |||
1413 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
1414 | return NULL((void*)0); | |||
1415 | } | |||
1416 | PyTuple_SET_ITEM(ret, iop, a)PyTuple_SetItem(ret, iop, a); | |||
1417 | } | |||
1418 | } | |||
1419 | ||||
1420 | return ret; | |||
1421 | } | |||
1422 | ||||
1423 | static PyObject *npyiter_operands_get(NewNpyArrayIterObject *self) | |||
1424 | { | |||
1425 | PyObject *ret; | |||
1426 | ||||
1427 | npy_intp iop, nop; | |||
1428 | PyArrayObject **operands; | |||
1429 | ||||
1430 | if (self->iter == NULL((void*)0)) { | |||
1431 | PyErr_SetString(PyExc_ValueError, | |||
1432 | "Iterator is invalid"); | |||
1433 | return NULL((void*)0); | |||
1434 | } | |||
1435 | nop = NpyIter_GetNOp(self->iter); | |||
1436 | operands = self->operands; | |||
1437 | ||||
1438 | ret = PyTuple_New(nop); | |||
1439 | if (ret == NULL((void*)0)) { | |||
1440 | return NULL((void*)0); | |||
1441 | } | |||
1442 | for (iop = 0; iop < nop; ++iop) { | |||
1443 | PyObject *operand = (PyObject *)operands[iop]; | |||
1444 | ||||
1445 | Py_INCREF(operand)_Py_INCREF(((PyObject*)(operand))); | |||
1446 | PyTuple_SET_ITEM(ret, iop, operand)PyTuple_SetItem(ret, iop, operand); | |||
1447 | } | |||
1448 | ||||
1449 | return ret; | |||
1450 | } | |||
1451 | ||||
1452 | static PyObject *npyiter_itviews_get(NewNpyArrayIterObject *self) | |||
1453 | { | |||
1454 | PyObject *ret; | |||
1455 | ||||
1456 | npy_intp iop, nop; | |||
1457 | ||||
1458 | if (self->iter == NULL((void*)0)) { | |||
1459 | PyErr_SetString(PyExc_ValueError, | |||
1460 | "Iterator is invalid"); | |||
1461 | return NULL((void*)0); | |||
1462 | } | |||
1463 | nop = NpyIter_GetNOp(self->iter); | |||
1464 | ||||
1465 | ret = PyTuple_New(nop); | |||
1466 | if (ret == NULL((void*)0)) { | |||
1467 | return NULL((void*)0); | |||
1468 | } | |||
1469 | for (iop = 0; iop < nop; ++iop) { | |||
1470 | PyArrayObject *view = NpyIter_GetIterView(self->iter, iop); | |||
1471 | ||||
1472 | if (view == NULL((void*)0)) { | |||
1473 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
1474 | return NULL((void*)0); | |||
1475 | } | |||
1476 | PyTuple_SET_ITEM(ret, iop, (PyObject *)view)PyTuple_SetItem(ret, iop, (PyObject *)view); | |||
1477 | } | |||
1478 | ||||
1479 | return ret; | |||
1480 | } | |||
1481 | ||||
1482 | static PyObject * | |||
1483 | npyiter_next(NewNpyArrayIterObject *self) | |||
1484 | { | |||
1485 | if (self->iter == NULL((void*)0) || self->iternext == NULL((void*)0) || | |||
1486 | self->finished) { | |||
1487 | return NULL((void*)0); | |||
1488 | } | |||
1489 | ||||
1490 | /* | |||
1491 | * Use the started flag for the Python iteration protocol to work | |||
1492 | * when buffering is enabled. | |||
1493 | */ | |||
1494 | if (self->started) { | |||
1495 | if (!self->iternext(self->iter)) { | |||
1496 | /* | |||
1497 | * A casting error may be set here (or no error causing a | |||
1498 | * StopIteration). Buffers may only be cleaned up later. | |||
1499 | */ | |||
1500 | self->finished = 1; | |||
1501 | return NULL((void*)0); | |||
1502 | } | |||
1503 | ||||
1504 | /* If there is nesting, the nested iterators should be reset */ | |||
1505 | if (npyiter_resetbasepointers(self) != NPY_SUCCEED1) { | |||
1506 | return NULL((void*)0); | |||
1507 | } | |||
1508 | } | |||
1509 | self->started = 1; | |||
1510 | ||||
1511 | return npyiter_value_get(self); | |||
1512 | }; | |||
1513 | ||||
1514 | static PyObject *npyiter_shape_get(NewNpyArrayIterObject *self) | |||
1515 | { | |||
1516 | npy_intp ndim, shape[NPY_MAXDIMS32]; | |||
1517 | ||||
1518 | if (self->iter == NULL((void*)0) || self->finished) { | |||
1519 | PyErr_SetString(PyExc_ValueError, | |||
1520 | "Iterator is past the end"); | |||
1521 | return NULL((void*)0); | |||
1522 | } | |||
1523 | ||||
1524 | if (NpyIter_GetShape(self->iter, shape) == NPY_SUCCEED1) { | |||
1525 | ndim = NpyIter_GetNDim(self->iter); | |||
1526 | return PyArray_IntTupleFromIntp(ndim, shape); | |||
1527 | } | |||
1528 | ||||
1529 | return NULL((void*)0); | |||
1530 | } | |||
1531 | ||||
1532 | static PyObject *npyiter_multi_index_get(NewNpyArrayIterObject *self) | |||
1533 | { | |||
1534 | npy_intp ndim, multi_index[NPY_MAXDIMS32]; | |||
1535 | ||||
1536 | if (self->iter == NULL((void*)0) || self->finished) { | |||
1537 | PyErr_SetString(PyExc_ValueError, | |||
1538 | "Iterator is past the end"); | |||
1539 | return NULL((void*)0); | |||
1540 | } | |||
1541 | ||||
1542 | if (self->get_multi_index != NULL((void*)0)) { | |||
1543 | ndim = NpyIter_GetNDim(self->iter); | |||
1544 | self->get_multi_index(self->iter, multi_index); | |||
1545 | return PyArray_IntTupleFromIntp(ndim, multi_index); | |||
1546 | } | |||
1547 | else { | |||
1548 | if (!NpyIter_HasMultiIndex(self->iter)) { | |||
1549 | PyErr_SetString(PyExc_ValueError, | |||
1550 | "Iterator is not tracking a multi-index"); | |||
1551 | return NULL((void*)0); | |||
1552 | } | |||
1553 | else if (NpyIter_HasDelayedBufAlloc(self->iter)) { | |||
1554 | PyErr_SetString(PyExc_ValueError, | |||
1555 | "Iterator construction used delayed buffer allocation, " | |||
1556 | "and no reset has been done yet"); | |||
1557 | return NULL((void*)0); | |||
1558 | } | |||
1559 | else { | |||
1560 | PyErr_SetString(PyExc_ValueError, | |||
1561 | "Iterator is in an invalid state"); | |||
1562 | return NULL((void*)0); | |||
1563 | } | |||
1564 | } | |||
1565 | } | |||
1566 | ||||
1567 | static int | |||
1568 | npyiter_multi_index_set(NewNpyArrayIterObject *self, PyObject *value) | |||
1569 | { | |||
1570 | npy_intp idim, ndim, multi_index[NPY_MAXDIMS32]; | |||
1571 | ||||
1572 | if (value == NULL((void*)0)) { | |||
| ||||
1573 | PyErr_SetString(PyExc_AttributeError, | |||
1574 | "Cannot delete nditer multi_index"); | |||
1575 | return -1; | |||
1576 | } | |||
1577 | if (self->iter == NULL((void*)0)) { | |||
1578 | PyErr_SetString(PyExc_ValueError, | |||
1579 | "Iterator is invalid"); | |||
1580 | return -1; | |||
1581 | } | |||
1582 | ||||
1583 | if (NpyIter_HasMultiIndex(self->iter)) { | |||
1584 | ndim = NpyIter_GetNDim(self->iter); | |||
1585 | if (!PySequence_Check(value)) { | |||
1586 | PyErr_SetString(PyExc_ValueError, | |||
1587 | "multi_index must be set with a sequence"); | |||
1588 | return -1; | |||
1589 | } | |||
1590 | if (PySequence_Size(value) != ndim) { | |||
1591 | PyErr_SetString(PyExc_ValueError, | |||
1592 | "Wrong number of indices"); | |||
1593 | return -1; | |||
1594 | } | |||
1595 | for (idim = 0; idim < ndim; ++idim) { | |||
1596 | PyObject *v = PySequence_GetItem(value, idim); | |||
| ||||
1597 | multi_index[idim] = PyLong_AsLong(v); | |||
1598 | if (error_converting(multi_index[idim])(((multi_index[idim]) == -1) && PyErr_Occurred())) { | |||
1599 | Py_XDECREF(v)_Py_XDECREF(((PyObject*)(v))); | |||
1600 | return -1; | |||
1601 | } | |||
1602 | } | |||
1603 | if (NpyIter_GotoMultiIndex(self->iter, multi_index) != NPY_SUCCEED1) { | |||
1604 | return -1; | |||
1605 | } | |||
1606 | self->started = 0; | |||
1607 | self->finished = 0; | |||
1608 | ||||
1609 | /* If there is nesting, the nested iterators should be reset */ | |||
1610 | if (npyiter_resetbasepointers(self) != NPY_SUCCEED1) { | |||
1611 | return -1; | |||
1612 | } | |||
1613 | ||||
1614 | return 0; | |||
1615 | } | |||
1616 | else { | |||
1617 | PyErr_SetString(PyExc_ValueError, | |||
1618 | "Iterator is not tracking a multi-index"); | |||
1619 | return -1; | |||
1620 | } | |||
1621 | } | |||
1622 | ||||
1623 | static PyObject *npyiter_index_get(NewNpyArrayIterObject *self) | |||
1624 | { | |||
1625 | if (self->iter == NULL((void*)0) || self->finished) { | |||
1626 | PyErr_SetString(PyExc_ValueError, | |||
1627 | "Iterator is past the end"); | |||
1628 | return NULL((void*)0); | |||
1629 | } | |||
1630 | ||||
1631 | if (NpyIter_HasIndex(self->iter)) { | |||
1632 | npy_intp ind = *NpyIter_GetIndexPtr(self->iter); | |||
1633 | return PyLong_FromLong(ind); | |||
1634 | } | |||
1635 | else { | |||
1636 | PyErr_SetString(PyExc_ValueError, | |||
1637 | "Iterator does not have an index"); | |||
1638 | return NULL((void*)0); | |||
1639 | } | |||
1640 | } | |||
1641 | ||||
1642 | static int npyiter_index_set(NewNpyArrayIterObject *self, PyObject *value) | |||
1643 | { | |||
1644 | if (value == NULL((void*)0)) { | |||
1645 | PyErr_SetString(PyExc_AttributeError, | |||
1646 | "Cannot delete nditer index"); | |||
1647 | return -1; | |||
1648 | } | |||
1649 | if (self->iter == NULL((void*)0)) { | |||
1650 | PyErr_SetString(PyExc_ValueError, | |||
1651 | "Iterator is invalid"); | |||
1652 | return -1; | |||
1653 | } | |||
1654 | ||||
1655 | if (NpyIter_HasIndex(self->iter)) { | |||
1656 | npy_intp ind; | |||
1657 | ind = PyLong_AsLong(value); | |||
1658 | if (error_converting(ind)(((ind) == -1) && PyErr_Occurred())) { | |||
1659 | return -1; | |||
1660 | } | |||
1661 | if (NpyIter_GotoIndex(self->iter, ind) != NPY_SUCCEED1) { | |||
1662 | return -1; | |||
1663 | } | |||
1664 | self->started = 0; | |||
1665 | self->finished = 0; | |||
1666 | ||||
1667 | /* If there is nesting, the nested iterators should be reset */ | |||
1668 | if (npyiter_resetbasepointers(self) != NPY_SUCCEED1) { | |||
1669 | return -1; | |||
1670 | } | |||
1671 | ||||
1672 | return 0; | |||
1673 | } | |||
1674 | else { | |||
1675 | PyErr_SetString(PyExc_ValueError, | |||
1676 | "Iterator does not have an index"); | |||
1677 | return -1; | |||
1678 | } | |||
1679 | } | |||
1680 | ||||
1681 | static PyObject *npyiter_iterindex_get(NewNpyArrayIterObject *self) | |||
1682 | { | |||
1683 | if (self->iter == NULL((void*)0) || self->finished) { | |||
1684 | PyErr_SetString(PyExc_ValueError, | |||
1685 | "Iterator is past the end"); | |||
1686 | return NULL((void*)0); | |||
1687 | } | |||
1688 | ||||
1689 | return PyLong_FromLong(NpyIter_GetIterIndex(self->iter)); | |||
1690 | } | |||
1691 | ||||
1692 | static int npyiter_iterindex_set(NewNpyArrayIterObject *self, PyObject *value) | |||
1693 | { | |||
1694 | npy_intp iterindex; | |||
1695 | ||||
1696 | if (value == NULL((void*)0)) { | |||
1697 | PyErr_SetString(PyExc_AttributeError, | |||
1698 | "Cannot delete nditer iterindex"); | |||
1699 | return -1; | |||
1700 | } | |||
1701 | if (self->iter == NULL((void*)0)) { | |||
1702 | PyErr_SetString(PyExc_ValueError, | |||
1703 | "Iterator is invalid"); | |||
1704 | return -1; | |||
1705 | } | |||
1706 | ||||
1707 | iterindex = PyLong_AsLong(value); | |||
1708 | if (error_converting(iterindex)(((iterindex) == -1) && PyErr_Occurred())) { | |||
1709 | return -1; | |||
1710 | } | |||
1711 | if (NpyIter_GotoIterIndex(self->iter, iterindex) != NPY_SUCCEED1) { | |||
1712 | return -1; | |||
1713 | } | |||
1714 | self->started = 0; | |||
1715 | self->finished = 0; | |||
1716 | ||||
1717 | /* If there is nesting, the nested iterators should be reset */ | |||
1718 | if (npyiter_resetbasepointers(self) != NPY_SUCCEED1) { | |||
1719 | return -1; | |||
1720 | } | |||
1721 | ||||
1722 | return 0; | |||
1723 | } | |||
1724 | ||||
1725 | static PyObject *npyiter_iterrange_get(NewNpyArrayIterObject *self) | |||
1726 | { | |||
1727 | npy_intp istart = 0, iend = 0; | |||
1728 | PyObject *ret; | |||
1729 | ||||
1730 | if (self->iter == NULL((void*)0)) { | |||
1731 | PyErr_SetString(PyExc_ValueError, | |||
1732 | "Iterator is invalid"); | |||
1733 | return NULL((void*)0); | |||
1734 | } | |||
1735 | ||||
1736 | NpyIter_GetIterIndexRange(self->iter, &istart, &iend); | |||
1737 | ||||
1738 | ret = PyTuple_New(2); | |||
1739 | if (ret == NULL((void*)0)) { | |||
1740 | return NULL((void*)0); | |||
1741 | } | |||
1742 | ||||
1743 | PyTuple_SET_ITEM(ret, 0, PyLong_FromLong(istart))PyTuple_SetItem(ret, 0, PyLong_FromLong(istart)); | |||
1744 | PyTuple_SET_ITEM(ret, 1, PyLong_FromLong(iend))PyTuple_SetItem(ret, 1, PyLong_FromLong(iend)); | |||
1745 | ||||
1746 | return ret; | |||
1747 | } | |||
1748 | ||||
1749 | static int npyiter_iterrange_set(NewNpyArrayIterObject *self, PyObject *value) | |||
1750 | { | |||
1751 | npy_intp istart = 0, iend = 0; | |||
1752 | ||||
1753 | if (value == NULL((void*)0)) { | |||
1754 | PyErr_SetString(PyExc_AttributeError, | |||
1755 | "Cannot delete nditer iterrange"); | |||
1756 | return -1; | |||
1757 | } | |||
1758 | if (self->iter == NULL((void*)0)) { | |||
1759 | PyErr_SetString(PyExc_ValueError, | |||
1760 | "Iterator is invalid"); | |||
1761 | return -1; | |||
1762 | } | |||
1763 | ||||
1764 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(value, "nn", &istart, &iend)) { | |||
1765 | return -1; | |||
1766 | } | |||
1767 | ||||
1768 | if (NpyIter_ResetToIterIndexRange(self->iter, istart, iend, NULL((void*)0)) | |||
1769 | != NPY_SUCCEED1) { | |||
1770 | return -1; | |||
1771 | } | |||
1772 | if (istart < iend) { | |||
1773 | self->started = self->finished = 0; | |||
1774 | } | |||
1775 | else { | |||
1776 | self->started = self->finished = 1; | |||
1777 | } | |||
1778 | ||||
1779 | if (self->get_multi_index == NULL((void*)0) && NpyIter_HasMultiIndex(self->iter)) { | |||
1780 | self->get_multi_index = NpyIter_GetGetMultiIndex(self->iter, NULL((void*)0)); | |||
1781 | } | |||
1782 | ||||
1783 | /* If there is nesting, the nested iterators should be reset */ | |||
1784 | if (npyiter_resetbasepointers(self) != NPY_SUCCEED1) { | |||
1785 | return -1; | |||
1786 | } | |||
1787 | ||||
1788 | return 0; | |||
1789 | } | |||
1790 | ||||
1791 | static PyObject *npyiter_has_delayed_bufalloc_get(NewNpyArrayIterObject *self) | |||
1792 | { | |||
1793 | if (self->iter == NULL((void*)0)) { | |||
1794 | PyErr_SetString(PyExc_ValueError, | |||
1795 | "Iterator is invalid"); | |||
1796 | return NULL((void*)0); | |||
1797 | } | |||
1798 | ||||
1799 | if (NpyIter_HasDelayedBufAlloc(self->iter)) { | |||
1800 | Py_RETURN_TRUEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct )))), ((PyObject *) &_Py_TrueStruct); | |||
1801 | } | |||
1802 | else { | |||
1803 | Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct )))), ((PyObject *) &_Py_FalseStruct); | |||
1804 | } | |||
1805 | } | |||
1806 | ||||
1807 | static PyObject *npyiter_iterationneedsapi_get(NewNpyArrayIterObject *self) | |||
1808 | { | |||
1809 | if (self->iter == NULL((void*)0)) { | |||
1810 | PyErr_SetString(PyExc_ValueError, | |||
1811 | "Iterator is invalid"); | |||
1812 | return NULL((void*)0); | |||
1813 | } | |||
1814 | ||||
1815 | if (NpyIter_IterationNeedsAPI(self->iter)) { | |||
1816 | Py_RETURN_TRUEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct )))), ((PyObject *) &_Py_TrueStruct); | |||
1817 | } | |||
1818 | else { | |||
1819 | Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct )))), ((PyObject *) &_Py_FalseStruct); | |||
1820 | } | |||
1821 | } | |||
1822 | ||||
1823 | static PyObject *npyiter_has_multi_index_get(NewNpyArrayIterObject *self) | |||
1824 | { | |||
1825 | if (self->iter == NULL((void*)0)) { | |||
1826 | PyErr_SetString(PyExc_ValueError, | |||
1827 | "Iterator is invalid"); | |||
1828 | return NULL((void*)0); | |||
1829 | } | |||
1830 | ||||
1831 | if (NpyIter_HasMultiIndex(self->iter)) { | |||
1832 | Py_RETURN_TRUEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct )))), ((PyObject *) &_Py_TrueStruct); | |||
1833 | } | |||
1834 | else { | |||
1835 | Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct )))), ((PyObject *) &_Py_FalseStruct); | |||
1836 | } | |||
1837 | } | |||
1838 | ||||
1839 | static PyObject *npyiter_has_index_get(NewNpyArrayIterObject *self) | |||
1840 | { | |||
1841 | if (self->iter == NULL((void*)0)) { | |||
1842 | PyErr_SetString(PyExc_ValueError, | |||
1843 | "Iterator is invalid"); | |||
1844 | return NULL((void*)0); | |||
1845 | } | |||
1846 | ||||
1847 | if (NpyIter_HasIndex(self->iter)) { | |||
1848 | Py_RETURN_TRUEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct )))), ((PyObject *) &_Py_TrueStruct); | |||
1849 | } | |||
1850 | else { | |||
1851 | Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct )))), ((PyObject *) &_Py_FalseStruct); | |||
1852 | } | |||
1853 | } | |||
1854 | ||||
1855 | static PyObject *npyiter_dtypes_get(NewNpyArrayIterObject *self) | |||
1856 | { | |||
1857 | PyObject *ret; | |||
1858 | ||||
1859 | npy_intp iop, nop; | |||
1860 | PyArray_Descr **dtypes; | |||
1861 | ||||
1862 | if (self->iter == NULL((void*)0)) { | |||
1863 | PyErr_SetString(PyExc_ValueError, | |||
1864 | "Iterator is invalid"); | |||
1865 | return NULL((void*)0); | |||
1866 | } | |||
1867 | nop = NpyIter_GetNOp(self->iter); | |||
1868 | ||||
1869 | ret = PyTuple_New(nop); | |||
1870 | if (ret == NULL((void*)0)) { | |||
1871 | return NULL((void*)0); | |||
1872 | } | |||
1873 | dtypes = self->dtypes; | |||
1874 | for (iop = 0; iop < nop; ++iop) { | |||
1875 | PyArray_Descr *dtype = dtypes[iop]; | |||
1876 | ||||
1877 | Py_INCREF(dtype)_Py_INCREF(((PyObject*)(dtype))); | |||
1878 | PyTuple_SET_ITEM(ret, iop, (PyObject *)dtype)PyTuple_SetItem(ret, iop, (PyObject *)dtype); | |||
1879 | } | |||
1880 | ||||
1881 | return ret; | |||
1882 | } | |||
1883 | ||||
1884 | static PyObject *npyiter_ndim_get(NewNpyArrayIterObject *self) | |||
1885 | { | |||
1886 | if (self->iter == NULL((void*)0)) { | |||
1887 | PyErr_SetString(PyExc_ValueError, | |||
1888 | "Iterator is invalid"); | |||
1889 | return NULL((void*)0); | |||
1890 | } | |||
1891 | ||||
1892 | return PyLong_FromLong(NpyIter_GetNDim(self->iter)); | |||
1893 | } | |||
1894 | ||||
1895 | static PyObject *npyiter_nop_get(NewNpyArrayIterObject *self) | |||
1896 | { | |||
1897 | if (self->iter == NULL((void*)0)) { | |||
1898 | PyErr_SetString(PyExc_ValueError, | |||
1899 | "Iterator is invalid"); | |||
1900 | return NULL((void*)0); | |||
1901 | } | |||
1902 | ||||
1903 | return PyLong_FromLong(NpyIter_GetNOp(self->iter)); | |||
1904 | } | |||
1905 | ||||
1906 | static PyObject *npyiter_itersize_get(NewNpyArrayIterObject *self) | |||
1907 | { | |||
1908 | if (self->iter == NULL((void*)0)) { | |||
1909 | PyErr_SetString(PyExc_ValueError, | |||
1910 | "Iterator is invalid"); | |||
1911 | return NULL((void*)0); | |||
1912 | } | |||
1913 | ||||
1914 | return PyLong_FromLong(NpyIter_GetIterSize(self->iter)); | |||
1915 | } | |||
1916 | ||||
1917 | static PyObject *npyiter_finished_get(NewNpyArrayIterObject *self) | |||
1918 | { | |||
1919 | if (self->iter == NULL((void*)0) || !self->finished) { | |||
1920 | Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct )))), ((PyObject *) &_Py_FalseStruct); | |||
1921 | } | |||
1922 | else { | |||
1923 | Py_RETURN_TRUEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct )))), ((PyObject *) &_Py_TrueStruct); | |||
1924 | } | |||
1925 | } | |||
1926 | ||||
1927 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) Py_ssize_t | |||
1928 | npyiter_seq_length(NewNpyArrayIterObject *self) | |||
1929 | { | |||
1930 | if (self->iter == NULL((void*)0)) { | |||
1931 | return 0; | |||
1932 | } | |||
1933 | else { | |||
1934 | return NpyIter_GetNOp(self->iter); | |||
1935 | } | |||
1936 | } | |||
1937 | ||||
1938 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | |||
1939 | npyiter_seq_item(NewNpyArrayIterObject *self, Py_ssize_t i) | |||
1940 | { | |||
1941 | npy_intp ret_ndim; | |||
1942 | npy_intp nop, innerloopsize, innerstride; | |||
1943 | char *dataptr; | |||
1944 | PyArray_Descr *dtype; | |||
1945 | int has_external_loop; | |||
1946 | Py_ssize_t i_orig = i; | |||
1947 | ||||
1948 | if (self->iter == NULL((void*)0) || self->finished) { | |||
1949 | PyErr_SetString(PyExc_ValueError, | |||
1950 | "Iterator is past the end"); | |||
1951 | return NULL((void*)0); | |||
1952 | } | |||
1953 | ||||
1954 | if (NpyIter_HasDelayedBufAlloc(self->iter)) { | |||
1955 | PyErr_SetString(PyExc_ValueError, | |||
1956 | "Iterator construction used delayed buffer allocation, " | |||
1957 | "and no reset has been done yet"); | |||
1958 | return NULL((void*)0); | |||
1959 | } | |||
1960 | nop = NpyIter_GetNOp(self->iter); | |||
1961 | ||||
1962 | /* Negative indexing */ | |||
1963 | if (i < 0) { | |||
1964 | i += nop; | |||
1965 | } | |||
1966 | ||||
1967 | if (i < 0 || i >= nop) { | |||
1968 | PyErr_Format(PyExc_IndexError, | |||
1969 | "Iterator operand index %zd is out of bounds", i_orig); | |||
1970 | return NULL((void*)0); | |||
1971 | } | |||
1972 | ||||
1973 | #if 0 | |||
1974 | /* | |||
1975 | * This check is disabled because it prevents things like | |||
1976 | * np.add(it[0], it[1], it[2]), where it[2] is a write-only | |||
1977 | * parameter. When write-only, the value of it[i] is | |||
1978 | * likely random junk, as if it were allocated with an | |||
1979 | * np.empty(...) call. | |||
1980 | */ | |||
1981 | if (!self->readflags[i]) { | |||
1982 | PyErr_Format(PyExc_RuntimeError, | |||
1983 | "Iterator operand %zd is write-only", i); | |||
1984 | return NULL((void*)0); | |||
1985 | } | |||
1986 | #endif | |||
1987 | ||||
1988 | dataptr = self->dataptrs[i]; | |||
1989 | dtype = self->dtypes[i]; | |||
1990 | has_external_loop = NpyIter_HasExternalLoop(self->iter); | |||
1991 | ||||
1992 | if (has_external_loop) { | |||
1993 | innerloopsize = *self->innerloopsizeptr; | |||
1994 | innerstride = self->innerstrides[i]; | |||
1995 | ret_ndim = 1; | |||
1996 | } | |||
1997 | else { | |||
1998 | innerloopsize = 1; | |||
1999 | innerstride = 0; | |||
2000 | /* If the iterator is going over every element, return array scalars */ | |||
2001 | ret_ndim = 0; | |||
2002 | } | |||
2003 | ||||
2004 | Py_INCREF(dtype)_Py_INCREF(((PyObject*)(dtype))); | |||
2005 | return PyArray_NewFromDescrAndBase( | |||
2006 | &PyArray_Type, dtype, | |||
2007 | ret_ndim, &innerloopsize, &innerstride, dataptr, | |||
2008 | self->writeflags[i] ? NPY_ARRAY_WRITEABLE0x0400 : 0, | |||
2009 | NULL((void*)0), (PyObject *)self); | |||
2010 | } | |||
2011 | ||||
2012 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | |||
2013 | npyiter_seq_slice(NewNpyArrayIterObject *self, | |||
2014 | Py_ssize_t ilow, Py_ssize_t ihigh) | |||
2015 | { | |||
2016 | PyObject *ret; | |||
2017 | npy_intp nop; | |||
2018 | Py_ssize_t i; | |||
2019 | ||||
2020 | if (self->iter == NULL((void*)0) || self->finished) { | |||
2021 | PyErr_SetString(PyExc_ValueError, | |||
2022 | "Iterator is past the end"); | |||
2023 | return NULL((void*)0); | |||
2024 | } | |||
2025 | ||||
2026 | if (NpyIter_HasDelayedBufAlloc(self->iter)) { | |||
2027 | PyErr_SetString(PyExc_ValueError, | |||
2028 | "Iterator construction used delayed buffer allocation, " | |||
2029 | "and no reset has been done yet"); | |||
2030 | return NULL((void*)0); | |||
2031 | } | |||
2032 | nop = NpyIter_GetNOp(self->iter); | |||
2033 | if (ilow < 0) { | |||
2034 | ilow = 0; | |||
2035 | } | |||
2036 | else if (ilow >= nop) { | |||
2037 | ilow = nop-1; | |||
2038 | } | |||
2039 | if (ihigh < ilow) { | |||
2040 | ihigh = ilow; | |||
2041 | } | |||
2042 | else if (ihigh > nop) { | |||
2043 | ihigh = nop; | |||
2044 | } | |||
2045 | ||||
2046 | ret = PyTuple_New(ihigh-ilow); | |||
2047 | if (ret == NULL((void*)0)) { | |||
2048 | return NULL((void*)0); | |||
2049 | } | |||
2050 | for (i = ilow; i < ihigh ; ++i) { | |||
2051 | PyObject *item = npyiter_seq_item(self, i); | |||
2052 | if (item == NULL((void*)0)) { | |||
2053 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
2054 | return NULL((void*)0); | |||
2055 | } | |||
2056 | PyTuple_SET_ITEM(ret, i-ilow, item)PyTuple_SetItem(ret, i-ilow, item); | |||
2057 | } | |||
2058 | return ret; | |||
2059 | } | |||
2060 | ||||
2061 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | |||
2062 | npyiter_seq_ass_item(NewNpyArrayIterObject *self, Py_ssize_t i, PyObject *v) | |||
2063 | { | |||
2064 | ||||
2065 | npy_intp nop, innerloopsize, innerstride; | |||
2066 | char *dataptr; | |||
2067 | PyArray_Descr *dtype; | |||
2068 | PyArrayObject *tmp; | |||
2069 | int ret, has_external_loop; | |||
2070 | Py_ssize_t i_orig = i; | |||
2071 | ||||
2072 | ||||
2073 | if (v == NULL((void*)0)) { | |||
2074 | PyErr_SetString(PyExc_TypeError, | |||
2075 | "Cannot delete iterator elements"); | |||
2076 | return -1; | |||
2077 | } | |||
2078 | ||||
2079 | if (self->iter == NULL((void*)0) || self->finished) { | |||
2080 | PyErr_SetString(PyExc_ValueError, | |||
2081 | "Iterator is past the end"); | |||
2082 | return -1; | |||
2083 | } | |||
2084 | ||||
2085 | if (NpyIter_HasDelayedBufAlloc(self->iter)) { | |||
2086 | PyErr_SetString(PyExc_ValueError, | |||
2087 | "Iterator construction used delayed buffer allocation, " | |||
2088 | "and no reset has been done yet"); | |||
2089 | return -1; | |||
2090 | } | |||
2091 | nop = NpyIter_GetNOp(self->iter); | |||
2092 | ||||
2093 | /* Negative indexing */ | |||
2094 | if (i < 0) { | |||
2095 | i += nop; | |||
2096 | } | |||
2097 | ||||
2098 | if (i < 0 || i >= nop) { | |||
2099 | PyErr_Format(PyExc_IndexError, | |||
2100 | "Iterator operand index %zd is out of bounds", i_orig); | |||
2101 | return -1; | |||
2102 | } | |||
2103 | if (!self->writeflags[i]) { | |||
2104 | PyErr_Format(PyExc_RuntimeError, | |||
2105 | "Iterator operand %zd is not writeable", i_orig); | |||
2106 | return -1; | |||
2107 | } | |||
2108 | ||||
2109 | dataptr = self->dataptrs[i]; | |||
2110 | dtype = self->dtypes[i]; | |||
2111 | has_external_loop = NpyIter_HasExternalLoop(self->iter); | |||
2112 | ||||
2113 | if (has_external_loop) { | |||
2114 | innerloopsize = *self->innerloopsizeptr; | |||
2115 | innerstride = self->innerstrides[i]; | |||
2116 | } | |||
2117 | else { | |||
2118 | innerloopsize = 1; | |||
2119 | innerstride = 0; | |||
2120 | } | |||
2121 | ||||
2122 | /* TODO - there should be a better way than this... */ | |||
2123 | Py_INCREF(dtype)_Py_INCREF(((PyObject*)(dtype))); | |||
2124 | tmp = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, dtype, | |||
2125 | 1, &innerloopsize, | |||
2126 | &innerstride, dataptr, | |||
2127 | NPY_ARRAY_WRITEABLE0x0400, NULL((void*)0)); | |||
2128 | if (tmp == NULL((void*)0)) { | |||
2129 | return -1; | |||
2130 | } | |||
2131 | ||||
2132 | ret = PyArray_CopyObject(tmp, v); | |||
2133 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | |||
2134 | return ret; | |||
2135 | } | |||
2136 | ||||
2137 | static int | |||
2138 | npyiter_seq_ass_slice(NewNpyArrayIterObject *self, Py_ssize_t ilow, | |||
2139 | Py_ssize_t ihigh, PyObject *v) | |||
2140 | { | |||
2141 | npy_intp nop; | |||
2142 | Py_ssize_t i; | |||
2143 | ||||
2144 | if (v == NULL((void*)0)) { | |||
2145 | PyErr_SetString(PyExc_TypeError, | |||
2146 | "Cannot delete iterator elements"); | |||
2147 | return -1; | |||
2148 | } | |||
2149 | ||||
2150 | if (self->iter == NULL((void*)0) || self->finished) { | |||
2151 | PyErr_SetString(PyExc_ValueError, | |||
2152 | "Iterator is past the end"); | |||
2153 | return -1; | |||
2154 | } | |||
2155 | ||||
2156 | if (NpyIter_HasDelayedBufAlloc(self->iter)) { | |||
2157 | PyErr_SetString(PyExc_ValueError, | |||
2158 | "Iterator construction used delayed buffer allocation, " | |||
2159 | "and no reset has been done yet"); | |||
2160 | return -1; | |||
2161 | } | |||
2162 | nop = NpyIter_GetNOp(self->iter); | |||
2163 | if (ilow < 0) { | |||
2164 | ilow = 0; | |||
2165 | } | |||
2166 | else if (ilow >= nop) { | |||
2167 | ilow = nop-1; | |||
2168 | } | |||
2169 | if (ihigh < ilow) { | |||
2170 | ihigh = ilow; | |||
2171 | } | |||
2172 | else if (ihigh > nop) { | |||
2173 | ihigh = nop; | |||
2174 | } | |||
2175 | ||||
2176 | if (!PySequence_Check(v) || PySequence_Size(v) != ihigh-ilow) { | |||
2177 | PyErr_SetString(PyExc_ValueError, | |||
2178 | "Wrong size to assign to iterator slice"); | |||
2179 | return -1; | |||
2180 | } | |||
2181 | ||||
2182 | for (i = ilow; i < ihigh ; ++i) { | |||
2183 | PyObject *item = PySequence_GetItem(v, i-ilow); | |||
2184 | if (item == NULL((void*)0)) { | |||
2185 | return -1; | |||
2186 | } | |||
2187 | if (npyiter_seq_ass_item(self, i, item) < 0) { | |||
2188 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
2189 | return -1; | |||
2190 | } | |||
2191 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
2192 | } | |||
2193 | ||||
2194 | return 0; | |||
2195 | } | |||
2196 | ||||
2197 | static PyObject * | |||
2198 | npyiter_subscript(NewNpyArrayIterObject *self, PyObject *op) | |||
2199 | { | |||
2200 | if (self->iter == NULL((void*)0) || self->finished) { | |||
2201 | PyErr_SetString(PyExc_ValueError, | |||
2202 | "Iterator is past the end"); | |||
2203 | return NULL((void*)0); | |||
2204 | } | |||
2205 | ||||
2206 | if (NpyIter_HasDelayedBufAlloc(self->iter)) { | |||
2207 | PyErr_SetString(PyExc_ValueError, | |||
2208 | "Iterator construction used delayed buffer allocation, " | |||
2209 | "and no reset has been done yet"); | |||
2210 | return NULL((void*)0); | |||
2211 | } | |||
2212 | ||||
2213 | if (PyLong_Check(op)((((((PyObject*)(op))->ob_type))->tp_flags & ((1UL << 24))) != 0) || | |||
2214 | (PyIndex_Check(op)((op)->ob_type->tp_as_number != ((void*)0) && ( op)->ob_type->tp_as_number->nb_index != ((void*)0)) && !PySequence_Check(op))) { | |||
2215 | npy_intp i = PyArray_PyIntAsIntp(op); | |||
2216 | if (error_converting(i)(((i) == -1) && PyErr_Occurred())) { | |||
2217 | return NULL((void*)0); | |||
2218 | } | |||
2219 | return npyiter_seq_item(self, i); | |||
2220 | } | |||
2221 | else if (PySlice_Check(op)((((PyObject*)(op))->ob_type) == &PySlice_Type)) { | |||
2222 | Py_ssize_t istart = 0, iend = 0, istep = 0, islicelength; | |||
2223 | if (PySlice_GetIndicesEx(op, NpyIter_GetNOp(self->iter),( PySlice_Unpack((op), (&istart), (&iend), (&istep )) < 0 ? ((*(&islicelength) = 0), -1) : ((*(&islicelength ) = PySlice_AdjustIndices((NpyIter_GetNOp(self->iter)), (& istart), (&iend), *(&istep))), 0)) | |||
2224 | &istart, &iend, &istep, &islicelength)( PySlice_Unpack((op), (&istart), (&iend), (&istep )) < 0 ? ((*(&islicelength) = 0), -1) : ((*(&islicelength ) = PySlice_AdjustIndices((NpyIter_GetNOp(self->iter)), (& istart), (&iend), *(&istep))), 0)) < 0) { | |||
2225 | return NULL((void*)0); | |||
2226 | } | |||
2227 | if (istep != 1) { | |||
2228 | PyErr_SetString(PyExc_ValueError, | |||
2229 | "Iterator slicing only supports a step of 1"); | |||
2230 | return NULL((void*)0); | |||
2231 | } | |||
2232 | return npyiter_seq_slice(self, istart, iend); | |||
2233 | } | |||
2234 | ||||
2235 | PyErr_SetString(PyExc_TypeError, | |||
2236 | "invalid index type for iterator indexing"); | |||
2237 | return NULL((void*)0); | |||
2238 | } | |||
2239 | ||||
2240 | static int | |||
2241 | npyiter_ass_subscript(NewNpyArrayIterObject *self, PyObject *op, | |||
2242 | PyObject *value) | |||
2243 | { | |||
2244 | if (value == NULL((void*)0)) { | |||
2245 | PyErr_SetString(PyExc_TypeError, | |||
2246 | "Cannot delete iterator elements"); | |||
2247 | return -1; | |||
2248 | } | |||
2249 | if (self->iter == NULL((void*)0) || self->finished) { | |||
2250 | PyErr_SetString(PyExc_ValueError, | |||
2251 | "Iterator is past the end"); | |||
2252 | return -1; | |||
2253 | } | |||
2254 | ||||
2255 | if (NpyIter_HasDelayedBufAlloc(self->iter)) { | |||
2256 | PyErr_SetString(PyExc_ValueError, | |||
2257 | "Iterator construction used delayed buffer allocation, " | |||
2258 | "and no reset has been done yet"); | |||
2259 | return -1; | |||
2260 | } | |||
2261 | ||||
2262 | if (PyLong_Check(op)((((((PyObject*)(op))->ob_type))->tp_flags & ((1UL << 24))) != 0) || | |||
2263 | (PyIndex_Check(op)((op)->ob_type->tp_as_number != ((void*)0) && ( op)->ob_type->tp_as_number->nb_index != ((void*)0)) && !PySequence_Check(op))) { | |||
2264 | npy_intp i = PyArray_PyIntAsIntp(op); | |||
2265 | if (error_converting(i)(((i) == -1) && PyErr_Occurred())) { | |||
2266 | return -1; | |||
2267 | } | |||
2268 | return npyiter_seq_ass_item(self, i, value); | |||
2269 | } | |||
2270 | else if (PySlice_Check(op)((((PyObject*)(op))->ob_type) == &PySlice_Type)) { | |||
2271 | Py_ssize_t istart = 0, iend = 0, istep = 0, islicelength = 0; | |||
2272 | if (PySlice_GetIndicesEx(op, NpyIter_GetNOp(self->iter),( PySlice_Unpack((op), (&istart), (&iend), (&istep )) < 0 ? ((*(&islicelength) = 0), -1) : ((*(&islicelength ) = PySlice_AdjustIndices((NpyIter_GetNOp(self->iter)), (& istart), (&iend), *(&istep))), 0)) | |||
2273 | &istart, &iend, &istep, &islicelength)( PySlice_Unpack((op), (&istart), (&iend), (&istep )) < 0 ? ((*(&islicelength) = 0), -1) : ((*(&islicelength ) = PySlice_AdjustIndices((NpyIter_GetNOp(self->iter)), (& istart), (&iend), *(&istep))), 0)) < 0) { | |||
2274 | return -1; | |||
2275 | } | |||
2276 | if (istep != 1) { | |||
2277 | PyErr_SetString(PyExc_ValueError, | |||
2278 | "Iterator slice assignment only supports a step of 1"); | |||
2279 | return -1; | |||
2280 | } | |||
2281 | return npyiter_seq_ass_slice(self, istart, iend, value); | |||
2282 | } | |||
2283 | ||||
2284 | PyErr_SetString(PyExc_TypeError, | |||
2285 | "invalid index type for iterator indexing"); | |||
2286 | return -1; | |||
2287 | } | |||
2288 | ||||
2289 | static PyObject * | |||
2290 | npyiter_enter(NewNpyArrayIterObject *self) | |||
2291 | { | |||
2292 | if (self->iter == NULL((void*)0)) { | |||
2293 | PyErr_SetString(PyExc_RuntimeError, "operation on non-initialized iterator"); | |||
2294 | return NULL((void*)0); | |||
2295 | } | |||
2296 | Py_INCREF(self)_Py_INCREF(((PyObject*)(self))); | |||
2297 | return (PyObject *)self; | |||
2298 | } | |||
2299 | ||||
2300 | static PyObject * | |||
2301 | npyiter_close(NewNpyArrayIterObject *self) | |||
2302 | { | |||
2303 | NpyIter *iter = self->iter; | |||
2304 | int ret; | |||
2305 | if (self->iter == NULL((void*)0)) { | |||
2306 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
2307 | } | |||
2308 | ret = NpyIter_Deallocate(iter); | |||
2309 | self->iter = NULL((void*)0); | |||
2310 | Py_XDECREF(self->nested_child)_Py_XDECREF(((PyObject*)(self->nested_child))); | |||
2311 | self->nested_child = NULL((void*)0); | |||
2312 | if (ret != NPY_SUCCEED1) { | |||
2313 | return NULL((void*)0); | |||
2314 | } | |||
2315 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
2316 | } | |||
2317 | ||||
2318 | static PyObject * | |||
2319 | npyiter_exit(NewNpyArrayIterObject *self, PyObject *NPY_UNUSED(args)(__NPY_UNUSED_TAGGEDargs) __attribute__ ((__unused__))) | |||
2320 | { | |||
2321 | /* even if called via exception handling, writeback any data */ | |||
2322 | return npyiter_close(self); | |||
2323 | } | |||
2324 | ||||
2325 | static PyMethodDef npyiter_methods[] = { | |||
2326 | {"reset", | |||
2327 | (PyCFunction)npyiter_reset, | |||
2328 | METH_NOARGS0x0004, NULL((void*)0)}, | |||
2329 | {"copy", | |||
2330 | (PyCFunction)npyiter_copy, | |||
2331 | METH_NOARGS0x0004, NULL((void*)0)}, | |||
2332 | {"__copy__", | |||
2333 | (PyCFunction)npyiter_copy, | |||
2334 | METH_NOARGS0x0004, NULL((void*)0)}, | |||
2335 | {"iternext", | |||
2336 | (PyCFunction)npyiter_iternext, | |||
2337 | METH_NOARGS0x0004, NULL((void*)0)}, | |||
2338 | {"remove_axis", | |||
2339 | (PyCFunction)npyiter_remove_axis, | |||
2340 | METH_VARARGS0x0001, NULL((void*)0)}, | |||
2341 | {"remove_multi_index", | |||
2342 | (PyCFunction)npyiter_remove_multi_index, | |||
2343 | METH_NOARGS0x0004, NULL((void*)0)}, | |||
2344 | {"enable_external_loop", | |||
2345 | (PyCFunction)npyiter_enable_external_loop, | |||
2346 | METH_NOARGS0x0004, NULL((void*)0)}, | |||
2347 | {"debug_print", | |||
2348 | (PyCFunction)npyiter_debug_print, | |||
2349 | METH_NOARGS0x0004, NULL((void*)0)}, | |||
2350 | {"__enter__", (PyCFunction)npyiter_enter, | |||
2351 | METH_NOARGS0x0004, NULL((void*)0)}, | |||
2352 | {"__exit__", (PyCFunction)npyiter_exit, | |||
2353 | METH_VARARGS0x0001, NULL((void*)0)}, | |||
2354 | {"close", (PyCFunction)npyiter_close, | |||
2355 | METH_NOARGS0x0004, NULL((void*)0)}, | |||
2356 | {NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)}, | |||
2357 | }; | |||
2358 | ||||
2359 | static PyMemberDef npyiter_members[] = { | |||
2360 | {NULL((void*)0), 0, 0, 0, NULL((void*)0)}, | |||
2361 | }; | |||
2362 | ||||
2363 | static PyGetSetDef npyiter_getsets[] = { | |||
2364 | {"value", | |||
2365 | (getter)npyiter_value_get, | |||
2366 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2367 | {"shape", | |||
2368 | (getter)npyiter_shape_get, | |||
2369 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2370 | {"multi_index", | |||
2371 | (getter)npyiter_multi_index_get, | |||
2372 | (setter)npyiter_multi_index_set, | |||
2373 | NULL((void*)0), NULL((void*)0)}, | |||
2374 | {"index", | |||
2375 | (getter)npyiter_index_get, | |||
2376 | (setter)npyiter_index_set, | |||
2377 | NULL((void*)0), NULL((void*)0)}, | |||
2378 | {"iterindex", | |||
2379 | (getter)npyiter_iterindex_get, | |||
2380 | (setter)npyiter_iterindex_set, | |||
2381 | NULL((void*)0), NULL((void*)0)}, | |||
2382 | {"iterrange", | |||
2383 | (getter)npyiter_iterrange_get, | |||
2384 | (setter)npyiter_iterrange_set, | |||
2385 | NULL((void*)0), NULL((void*)0)}, | |||
2386 | {"operands", | |||
2387 | (getter)npyiter_operands_get, | |||
2388 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2389 | {"itviews", | |||
2390 | (getter)npyiter_itviews_get, | |||
2391 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2392 | {"has_delayed_bufalloc", | |||
2393 | (getter)npyiter_has_delayed_bufalloc_get, | |||
2394 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2395 | {"iterationneedsapi", | |||
2396 | (getter)npyiter_iterationneedsapi_get, | |||
2397 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2398 | {"has_multi_index", | |||
2399 | (getter)npyiter_has_multi_index_get, | |||
2400 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2401 | {"has_index", | |||
2402 | (getter)npyiter_has_index_get, | |||
2403 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2404 | {"dtypes", | |||
2405 | (getter)npyiter_dtypes_get, | |||
2406 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2407 | {"ndim", | |||
2408 | (getter)npyiter_ndim_get, | |||
2409 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2410 | {"nop", | |||
2411 | (getter)npyiter_nop_get, | |||
2412 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2413 | {"itersize", | |||
2414 | (getter)npyiter_itersize_get, | |||
2415 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2416 | {"finished", | |||
2417 | (getter)npyiter_finished_get, | |||
2418 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
2419 | ||||
2420 | {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)} | |||
2421 | }; | |||
2422 | ||||
2423 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PySequenceMethods npyiter_as_sequence = { | |||
2424 | (lenfunc)npyiter_seq_length, /*sq_length*/ | |||
2425 | (binaryfunc)NULL((void*)0), /*sq_concat*/ | |||
2426 | (ssizeargfunc)NULL((void*)0), /*sq_repeat*/ | |||
2427 | (ssizeargfunc)npyiter_seq_item, /*sq_item*/ | |||
2428 | (ssizessizeargfunc)NULL((void*)0), /*sq_slice*/ | |||
2429 | (ssizeobjargproc)npyiter_seq_ass_item, /*sq_ass_item*/ | |||
2430 | (ssizessizeobjargproc)NULL((void*)0), /*sq_ass_slice*/ | |||
2431 | (objobjproc)NULL((void*)0), /*sq_contains */ | |||
2432 | (binaryfunc)NULL((void*)0), /*sq_inplace_concat */ | |||
2433 | (ssizeargfunc)NULL((void*)0), /*sq_inplace_repeat */ | |||
2434 | }; | |||
2435 | ||||
2436 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyMappingMethods npyiter_as_mapping = { | |||
2437 | (lenfunc)npyiter_seq_length, /*mp_length*/ | |||
2438 | (binaryfunc)npyiter_subscript, /*mp_subscript*/ | |||
2439 | (objobjargproc)npyiter_ass_subscript, /*mp_ass_subscript*/ | |||
2440 | }; | |||
2441 | ||||
2442 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyTypeObject NpyIter_Type = { | |||
2443 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | |||
2444 | .tp_name = "numpy.nditer", | |||
2445 | .tp_basicsize = sizeof(NewNpyArrayIterObject), | |||
2446 | .tp_dealloc = (destructor)npyiter_dealloc, | |||
2447 | .tp_as_sequence = &npyiter_as_sequence, | |||
2448 | .tp_as_mapping = &npyiter_as_mapping, | |||
2449 | .tp_flags = Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0), | |||
2450 | .tp_iternext = (iternextfunc)npyiter_next, | |||
2451 | .tp_methods = npyiter_methods, | |||
2452 | .tp_members = npyiter_members, | |||
2453 | .tp_getset = npyiter_getsets, | |||
2454 | .tp_init = (initproc)npyiter_init, | |||
2455 | .tp_new = npyiter_new, | |||
2456 | }; |
1 | #ifndef PySequence_GetItem |
2 | struct _object; |
3 | typedef struct _object PyObject; |
4 | PyObject* clang_analyzer_PyObject_New_Reference(); |
5 | PyObject* PySequence_GetItem(PyObject *o, Py_ssize_t i) { |
6 | return clang_analyzer_PyObject_New_Reference(); |
7 | } |
8 | #else |
9 | #warning "API PySequence_GetItem is defined as a macro." |
10 | #endif |