File: | np/ufunc/_internal.c |
Warning: | line 674, column 5 PyObject ownership leak with reference count of 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | #include "_internal.h" | |||
2 | #include "Python.h" | |||
3 | ||||
4 | /* A small object that handles deallocation of some of a PyUFunc's fields */ | |||
5 | typedef struct { | |||
6 | PyObject_HEADPyObject ob_base; | |||
7 | /* Borrowed reference */ | |||
8 | PyUFuncObject *ufunc; | |||
9 | /* Owned reference to ancillary object */ | |||
10 | PyObject *object; | |||
11 | } PyUFuncCleaner; | |||
12 | ||||
13 | PyTypeObject PyUFuncCleaner_Type; | |||
14 | ||||
15 | ||||
16 | static PyObject * | |||
17 | cleaner_new(PyUFuncObject *ufunc, PyObject *object) | |||
18 | { | |||
19 | PyUFuncCleaner *obj = PyObject_New(PyUFuncCleaner, &PyUFuncCleaner_Type)( (PyUFuncCleaner *) _PyObject_New(&PyUFuncCleaner_Type) ); | |||
20 | if (obj != NULL((void*)0)) { | |||
21 | obj->ufunc = ufunc; | |||
22 | Py_XINCREF(object)_Py_XINCREF(((PyObject*)(object))); | |||
23 | obj->object = object; | |||
24 | } | |||
25 | return (PyObject *) obj; | |||
26 | } | |||
27 | ||||
28 | /* Deallocate the PyArray_malloc calls */ | |||
29 | static void | |||
30 | cleaner_dealloc(PyUFuncCleaner *self) | |||
31 | { | |||
32 | PyUFuncObject *ufunc = self->ufunc; | |||
33 | Py_XDECREF(self->object)_Py_XDECREF(((PyObject*)(self->object))); | |||
34 | if (ufunc->functions) | |||
35 | PyArray_freePyMem_RawFree(ufunc->functions); | |||
36 | if (ufunc->types) | |||
37 | PyArray_freePyMem_RawFree(ufunc->types); | |||
38 | if (ufunc->data) | |||
39 | PyArray_freePyMem_RawFree(ufunc->data); | |||
40 | PyObject_DelPyObject_Free(self); | |||
41 | } | |||
42 | ||||
43 | PyTypeObject PyUFuncCleaner_Type = { | |||
44 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | |||
45 | "numba._UFuncCleaner", /* tp_name*/ | |||
46 | sizeof(PyUFuncCleaner), /* tp_basicsize*/ | |||
47 | 0, /* tp_itemsize */ | |||
48 | /* methods */ | |||
49 | (destructor) cleaner_dealloc, /* tp_dealloc */ | |||
50 | 0, /* tp_print */ | |||
51 | 0, /* tp_getattr */ | |||
52 | 0, /* tp_setattr */ | |||
53 | #if defined(NPY_PY3K) | |||
54 | 0, /* tp_reserved */ | |||
55 | #else | |||
56 | 0, /* tp_compare */ | |||
57 | #endif | |||
58 | 0, /* tp_repr */ | |||
59 | 0, /* tp_as_number */ | |||
60 | 0, /* tp_as_sequence */ | |||
61 | 0, /* tp_as_mapping */ | |||
62 | 0, /* tp_hash */ | |||
63 | 0, /* tp_call */ | |||
64 | 0, /* tp_str */ | |||
65 | 0, /* tp_getattro */ | |||
66 | 0, /* tp_setattro */ | |||
67 | 0, /* tp_as_buffer */ | |||
68 | Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0), /* tp_flags */ | |||
69 | 0, /* tp_doc */ | |||
70 | 0, /* tp_traverse */ | |||
71 | 0, /* tp_clear */ | |||
72 | 0, /* tp_richcompare */ | |||
73 | 0, /* tp_weaklistoffset */ | |||
74 | 0, /* tp_iter */ | |||
75 | 0, /* tp_iternext */ | |||
76 | 0, /* tp_methods */ | |||
77 | 0, /* tp_members */ | |||
78 | 0, /* tp_getset */ | |||
79 | 0, /* tp_base */ | |||
80 | 0, /* tp_dict */ | |||
81 | 0, /* tp_descr_get */ | |||
82 | 0, /* tp_descr_set */ | |||
83 | 0, /* tp_dictoffset */ | |||
84 | 0, /* tp_init */ | |||
85 | 0, /* tp_alloc */ | |||
86 | 0, /* tp_new */ | |||
87 | 0, /* tp_free */ | |||
88 | 0, /* tp_is_gc */ | |||
89 | 0, /* tp_bases */ | |||
90 | 0, /* tp_mro */ | |||
91 | 0, /* tp_cache */ | |||
92 | 0, /* tp_subclasses */ | |||
93 | 0, /* tp_weaklist */ | |||
94 | 0, /* tp_del */ | |||
95 | 0, /* tp_version_tag */ | |||
96 | }; | |||
97 | ||||
98 | /* ______________________________________________________________________ | |||
99 | * DUFunc: A call-time (hence dynamic) specializable ufunc. | |||
100 | */ | |||
101 | ||||
102 | typedef struct { | |||
103 | PyObject_HEADPyObject ob_base; | |||
104 | PyObject * dispatcher; | |||
105 | PyUFuncObject * ufunc; | |||
106 | PyObject * keepalive; | |||
107 | int frozen; | |||
108 | } PyDUFuncObject; | |||
109 | ||||
110 | static void | |||
111 | dufunc_dealloc(PyDUFuncObject *self) | |||
112 | { | |||
113 | /* Note: There is no need to call PyArray_free() on | |||
114 | self->ufunc->ptr, since ufunc_dealloc() will do it for us. */ | |||
115 | Py_XDECREF(self->ufunc)_Py_XDECREF(((PyObject*)(self->ufunc))); | |||
116 | Py_XDECREF(self->dispatcher)_Py_XDECREF(((PyObject*)(self->dispatcher))); | |||
117 | Py_XDECREF(self->keepalive)_Py_XDECREF(((PyObject*)(self->keepalive))); | |||
118 | Py_TYPE(self)(((PyObject*)(self))->ob_type)->tp_free((PyObject *)self); | |||
119 | } | |||
120 | ||||
121 | static PyObject * | |||
122 | dufunc_repr(PyDUFuncObject *dufunc) | |||
123 | { | |||
124 | return PyString_FromFormatPyUnicode_FromFormat("<numba._DUFunc '%s'>", dufunc->ufunc->name); | |||
125 | } | |||
126 | ||||
127 | static PyObject * | |||
128 | dufunc_call(PyDUFuncObject *self, PyObject *args, PyObject *kws) | |||
129 | { | |||
130 | PyObject *result=NULL((void*)0), *method=NULL((void*)0); | |||
131 | ||||
132 | result = PyUFunc_Type(*(PyTypeObject *)PyUFunc_API[0]).tp_call((PyObject *)self->ufunc, args, kws); | |||
133 | if ((!self->frozen) && | |||
134 | (result == NULL((void*)0)) && | |||
135 | (PyErr_Occurred()) && | |||
136 | (PyErr_ExceptionMatches(PyExc_TypeError))) { | |||
137 | ||||
138 | /* Break back into Python when we fail at dispatch. */ | |||
139 | PyErr_Clear(); | |||
140 | method = PyObject_GetAttrString((PyObject*)self, "_compile_for_args"); | |||
141 | ||||
142 | if (method) { | |||
143 | result = PyObject_Call(method, args, kws); | |||
144 | if (result) { | |||
145 | Py_DECREF(result)_Py_DECREF(((PyObject*)(result))); | |||
146 | result = PyUFunc_Type(*(PyTypeObject *)PyUFunc_API[0]).tp_call((PyObject *)self->ufunc, args, | |||
147 | kws); | |||
148 | } | |||
149 | } | |||
150 | Py_XDECREF(method)_Py_XDECREF(((PyObject*)(method))); | |||
151 | } | |||
152 | return result; | |||
153 | } | |||
154 | ||||
155 | static Py_ssize_t | |||
156 | _get_nin(PyObject * py_func_obj) | |||
157 | { | |||
158 | int result = -1; | |||
159 | PyObject *inspect=NULL((void*)0), *getargspec=NULL((void*)0), *argspec=NULL((void*)0), *args=NULL((void*)0); | |||
160 | ||||
161 | inspect = PyImport_ImportModule("inspect"); | |||
162 | if (!inspect) goto _get_nin_cleanup; | |||
163 | getargspec = PyObject_GetAttrString(inspect, "getfullargspec"); | |||
164 | if (!getargspec) goto _get_nin_cleanup; | |||
165 | argspec = PyObject_CallFunctionObjArgs(getargspec, py_func_obj, NULL((void*)0)); | |||
166 | if (!argspec) goto _get_nin_cleanup; | |||
167 | args = PyObject_GetAttrString(argspec, "args"); | |||
168 | if (!args) goto _get_nin_cleanup; | |||
169 | result = PyList_Size(args); | |||
170 | ||||
171 | _get_nin_cleanup: | |||
172 | Py_XDECREF(args)_Py_XDECREF(((PyObject*)(args))); | |||
173 | Py_XDECREF(argspec)_Py_XDECREF(((PyObject*)(argspec))); | |||
174 | Py_XDECREF(getargspec)_Py_XDECREF(((PyObject*)(getargspec))); | |||
175 | Py_XDECREF(inspect)_Py_XDECREF(((PyObject*)(inspect))); | |||
176 | return result; | |||
177 | } | |||
178 | ||||
179 | static int | |||
180 | dufunc_init(PyDUFuncObject *self, PyObject *args, PyObject *kws) | |||
181 | { | |||
182 | PyObject *dispatcher=NULL((void*)0), *keepalive=NULL((void*)0), *py_func_obj=NULL((void*)0), *tmp; | |||
183 | PyUFuncObject *ufunc=NULL((void*)0); | |||
184 | int identity=PyUFunc_None-1; | |||
185 | int nin=-1, nout=1; | |||
186 | const char *name=NULL((void*)0), *doc=NULL((void*)0); | |||
187 | ||||
188 | static char * kwlist[] = {"dispatcher", "identity", "_keepalive", "nin", | |||
189 | "nout", NULL((void*)0)}; | |||
190 | ||||
191 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, kws, "O|iO!nn", kwlist, | |||
192 | &dispatcher, &identity, | |||
193 | &PyList_Type, &keepalive, &nin, &nout)) { | |||
194 | return -1; | |||
195 | } | |||
196 | ||||
197 | py_func_obj = PyObject_GetAttrString(dispatcher, "py_func"); | |||
198 | if (!py_func_obj) { | |||
199 | return -1; | |||
200 | } | |||
201 | ||||
202 | if (nin < 0) { | |||
203 | nin = (int)_get_nin(py_func_obj); | |||
204 | if ((nin < 0) || (PyErr_Occurred())) { | |||
205 | Py_XDECREF(py_func_obj)_Py_XDECREF(((PyObject*)(py_func_obj))); | |||
206 | return -1; | |||
207 | } | |||
208 | } | |||
209 | ||||
210 | /* Construct the UFunc. */ | |||
211 | tmp = PyObject_GetAttrString(py_func_obj, "__name__"); | |||
212 | if (tmp) { | |||
213 | name = PyString_AsStringPyUnicode_AsUTF8(tmp); | |||
214 | } | |||
215 | Py_XDECREF(tmp)_Py_XDECREF(((PyObject*)(tmp))); | |||
216 | tmp = PyObject_GetAttrString(py_func_obj, "__doc__"); | |||
217 | if (tmp && (tmp != Py_None(&_Py_NoneStruct))) { | |||
218 | doc = PyString_AsStringPyUnicode_AsUTF8(tmp); | |||
219 | } | |||
220 | Py_XDECREF(tmp)_Py_XDECREF(((PyObject*)(tmp))); | |||
221 | tmp = NULL((void*)0); | |||
222 | Py_XDECREF(py_func_obj)_Py_XDECREF(((PyObject*)(py_func_obj))); | |||
223 | py_func_obj = NULL((void*)0); | |||
224 | if (!name) { | |||
225 | return -1; | |||
226 | } | |||
227 | ufunc = (PyUFuncObject *)PyUFunc_FromFuncAndData(*(PyObject * (*)(PyUFuncGenericFunction *, void **, char *, int , int, int, int, const char *, const char *, int)) PyUFunc_API [1])(NULL((void*)0), NULL((void*)0), NULL((void*)0), 0, | |||
228 | nin, nout, identity, | |||
229 | name, doc, 0); | |||
230 | if (!ufunc) { | |||
231 | return -1; | |||
232 | } | |||
233 | ||||
234 | /* Construct a keepalive list if none was given. */ | |||
235 | if (!keepalive) { | |||
236 | keepalive = PyList_New(0); | |||
237 | if (!keepalive) { | |||
238 | Py_XDECREF(ufunc)_Py_XDECREF(((PyObject*)(ufunc))); | |||
239 | return -1; | |||
240 | } | |||
241 | } else { | |||
242 | Py_INCREF(keepalive)_Py_INCREF(((PyObject*)(keepalive))); | |||
243 | } | |||
244 | ||||
245 | tmp = self->dispatcher; | |||
246 | Py_INCREF(dispatcher)_Py_INCREF(((PyObject*)(dispatcher))); | |||
247 | self->dispatcher = dispatcher; | |||
248 | Py_XDECREF(tmp)_Py_XDECREF(((PyObject*)(tmp))); | |||
249 | ||||
250 | tmp = (PyObject*)self->ufunc; | |||
251 | self->ufunc = ufunc; | |||
252 | Py_XDECREF(tmp)_Py_XDECREF(((PyObject*)(tmp))); | |||
253 | ||||
254 | tmp = self->keepalive; | |||
255 | /* Already incref'ed, either by PyList_New(), or else clause, both above. */ | |||
256 | self->keepalive = keepalive; | |||
257 | Py_XDECREF(tmp)_Py_XDECREF(((PyObject*)(tmp))); | |||
258 | ||||
259 | self->frozen = 0; | |||
260 | ||||
261 | return 0; | |||
262 | } | |||
263 | ||||
264 | static PyMemberDef dufunc_members[] = { | |||
265 | {"_dispatcher", T_OBJECT_EX16, offsetof(PyDUFuncObject, dispatcher)__builtin_offsetof(PyDUFuncObject, dispatcher), 0, | |||
266 | "Dispatcher object for the core Python function."}, | |||
267 | {"ufunc", T_OBJECT_EX16, offsetof(PyDUFuncObject, ufunc)__builtin_offsetof(PyDUFuncObject, ufunc), 0, | |||
268 | "Numpy Ufunc for the dynamic ufunc."}, | |||
269 | {"_keepalive", T_OBJECT_EX16, offsetof(PyDUFuncObject, keepalive)__builtin_offsetof(PyDUFuncObject, keepalive), 0, | |||
270 | "List of objects to keep alive during life of dufunc."}, | |||
271 | {NULL((void*)0)} | |||
272 | }; | |||
273 | ||||
274 | /* ____________________________________________________________ | |||
275 | * Shims to expose ufunc methods. | |||
276 | */ | |||
277 | ||||
278 | static struct _ufunc_dispatch { | |||
279 | PyCFunctionWithKeywords ufunc_reduce; | |||
280 | PyCFunctionWithKeywords ufunc_accumulate; | |||
281 | PyCFunctionWithKeywords ufunc_reduceat; | |||
282 | PyCFunctionWithKeywords ufunc_outer; | |||
283 | #if NPY_API_VERSION0x0000000D >= 0x00000008 | |||
284 | PyCFunction ufunc_at; | |||
285 | #endif | |||
286 | } ufunc_dispatch; | |||
287 | ||||
288 | static int | |||
289 | init_ufunc_dispatch(void) | |||
290 | { | |||
291 | int result = 0; | |||
292 | PyMethodDef * crnt = PyUFunc_Type(*(PyTypeObject *)PyUFunc_API[0]).tp_methods; | |||
293 | const char * crnt_name = NULL((void*)0); | |||
294 | for (; crnt->ml_name != NULL((void*)0); crnt++) { | |||
295 | crnt_name = crnt->ml_name; | |||
296 | switch(crnt_name[0]) { | |||
297 | case 'a': | |||
298 | if (strncmp(crnt_name, "accumulate", 11) == 0) { | |||
299 | ufunc_dispatch.ufunc_accumulate = | |||
300 | (PyCFunctionWithKeywords)crnt->ml_meth; | |||
301 | #if NPY_API_VERSION0x0000000D >= 0x00000008 | |||
302 | } else if (strncmp(crnt_name, "at", 3) == 0) { | |||
303 | ufunc_dispatch.ufunc_at = crnt->ml_meth; | |||
304 | #endif | |||
305 | } else { | |||
306 | result = -1; | |||
307 | } | |||
308 | break; | |||
309 | case 'o': | |||
310 | if (strncmp(crnt_name, "outer", 6) == 0) { | |||
311 | ufunc_dispatch.ufunc_outer = | |||
312 | (PyCFunctionWithKeywords)crnt->ml_meth; | |||
313 | } else { | |||
314 | result = -1; | |||
315 | } | |||
316 | break; | |||
317 | case 'r': | |||
318 | if (strncmp(crnt_name, "reduce", 7) == 0) { | |||
319 | ufunc_dispatch.ufunc_reduce = | |||
320 | (PyCFunctionWithKeywords)crnt->ml_meth; | |||
321 | } else if (strncmp(crnt_name, "reduceat", 9) == 0) { | |||
322 | ufunc_dispatch.ufunc_reduceat = | |||
323 | (PyCFunctionWithKeywords)crnt->ml_meth; | |||
324 | } else { | |||
325 | result = -1; | |||
326 | } | |||
327 | break; | |||
328 | default: | |||
329 | result = -1; /* Unknown method */ | |||
330 | } | |||
331 | if (result < 0) break; | |||
332 | } | |||
333 | if (result == 0) { | |||
334 | /* Sanity check. */ | |||
335 | result = ((ufunc_dispatch.ufunc_reduce != NULL((void*)0)) | |||
336 | && (ufunc_dispatch.ufunc_accumulate != NULL((void*)0)) | |||
337 | && (ufunc_dispatch.ufunc_reduceat != NULL((void*)0)) | |||
338 | && (ufunc_dispatch.ufunc_outer != NULL((void*)0)) | |||
339 | #if NPY_API_VERSION0x0000000D >= 0x00000008 | |||
340 | && (ufunc_dispatch.ufunc_at != NULL((void*)0)) | |||
341 | #endif | |||
342 | ); | |||
343 | } | |||
344 | return result; | |||
345 | } | |||
346 | ||||
347 | static PyObject * | |||
348 | dufunc_reduce(PyDUFuncObject * self, PyObject * args, PyObject *kws) | |||
349 | { | |||
350 | return ufunc_dispatch.ufunc_reduce((PyObject*)self->ufunc, args, kws); | |||
351 | } | |||
352 | ||||
353 | static PyObject * | |||
354 | dufunc_accumulate(PyDUFuncObject * self, PyObject * args, PyObject *kws) | |||
355 | { | |||
356 | return ufunc_dispatch.ufunc_accumulate((PyObject*)self->ufunc, args, kws); | |||
357 | } | |||
358 | ||||
359 | static PyObject * | |||
360 | dufunc_reduceat(PyDUFuncObject * self, PyObject * args, PyObject *kws) | |||
361 | { | |||
362 | return ufunc_dispatch.ufunc_reduceat((PyObject*)self->ufunc, args, kws); | |||
363 | } | |||
364 | ||||
365 | static PyObject * | |||
366 | dufunc_outer(PyDUFuncObject * self, PyObject * args, PyObject *kws) | |||
367 | { | |||
368 | return ufunc_dispatch.ufunc_outer((PyObject*)self->ufunc, args, kws); | |||
369 | } | |||
370 | ||||
371 | #if NPY_API_VERSION0x0000000D >= 0x00000008 | |||
372 | static PyObject * | |||
373 | dufunc_at(PyDUFuncObject * self, PyObject * args) | |||
374 | { | |||
375 | return ufunc_dispatch.ufunc_at((PyObject*)self->ufunc, args); | |||
376 | } | |||
377 | #endif | |||
378 | ||||
379 | static PyObject * | |||
380 | dufunc__compile_for_args(PyDUFuncObject * self, PyObject * args, | |||
381 | PyObject * kws) | |||
382 | { | |||
383 | PyErr_SetString(PyExc_NotImplementedError, | |||
384 | "Abstract method _DUFunc._compile_for_args() called!"); | |||
385 | return NULL((void*)0); | |||
386 | } | |||
387 | ||||
388 | static int * | |||
389 | _build_arg_types_array(PyObject * type_list, Py_ssize_t nargs) | |||
390 | { | |||
391 | int *arg_types_array=NULL((void*)0); | |||
392 | Py_ssize_t idx, arg_types_size = PyList_Size(type_list); | |||
393 | ||||
394 | if (arg_types_size != nargs) { | |||
395 | PyErr_SetString( | |||
396 | PyExc_ValueError, | |||
397 | "argument type list size does not equal ufunc argument count"); | |||
398 | return NULL((void*)0); | |||
399 | } | |||
400 | arg_types_array = PyArray_mallocPyMem_RawMalloc(sizeof(int) * nargs); | |||
401 | if (!arg_types_array) { | |||
402 | PyErr_NoMemory(); | |||
403 | return NULL((void*)0); | |||
404 | } | |||
405 | for (idx = 0; idx < nargs; idx++) { | |||
406 | arg_types_array[idx] = (int)PyLong_AsLong(PyList_GET_ITEM(type_list,(((PyListObject *)(type_list))->ob_item[idx]) | |||
407 | idx)(((PyListObject *)(type_list))->ob_item[idx])); | |||
408 | } | |||
409 | if (PyErr_Occurred()) { | |||
410 | PyArray_freePyMem_RawFree(arg_types_array); | |||
411 | arg_types_array = NULL((void*)0); | |||
412 | } | |||
413 | return arg_types_array; | |||
414 | } | |||
415 | ||||
416 | static PyObject * | |||
417 | dufunc__add_loop(PyDUFuncObject * self, PyObject * args) | |||
418 | { | |||
419 | PyUFuncObject * ufunc=self->ufunc; | |||
420 | void *loop_ptr=NULL((void*)0), *data_ptr=NULL((void*)0); | |||
421 | int idx=-1, usertype=NPY_VOID; | |||
422 | int *arg_types_arr=NULL((void*)0); | |||
423 | PyObject *arg_types=NULL((void*)0), *loop_obj=NULL((void*)0), *data_obj=NULL((void*)0); | |||
424 | PyUFuncGenericFunction old_func=NULL((void*)0); | |||
425 | ||||
426 | if (self->frozen) { | |||
427 | PyErr_SetString(PyExc_ValueError, | |||
428 | "_DUFunc._add_loop() called for frozen dufunc"); | |||
429 | return NULL((void*)0); | |||
430 | } | |||
431 | ||||
432 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "O!O!|O!", | |||
433 | &PyLong_Type, &loop_obj, &PyList_Type, &arg_types, | |||
434 | &PyLong_Type, &data_obj)) { | |||
435 | return NULL((void*)0); | |||
436 | } | |||
437 | ||||
438 | loop_ptr = PyLong_AsVoidPtr(loop_obj); | |||
439 | if (PyErr_Occurred()) { | |||
440 | return NULL((void*)0); | |||
441 | } | |||
442 | if (data_obj) { | |||
443 | data_ptr = PyLong_AsVoidPtr(data_obj); | |||
444 | if (PyErr_Occurred()) { | |||
445 | return NULL((void*)0); | |||
446 | } | |||
447 | } | |||
448 | ||||
449 | arg_types_arr = _build_arg_types_array(arg_types, (Py_ssize_t)ufunc->nargs); | |||
450 | if (!arg_types_arr) goto _dufunc__add_loop_fail; | |||
451 | ||||
452 | /* Check to see if any of the input types are user defined dtypes. | |||
453 | If they are, we should use PyUFunc_RegisterLoopForType() since | |||
454 | dispatch on a user defined dtype uses a Python dictionary | |||
455 | keyed by usertype (and not the functions array). | |||
456 | ||||
457 | For more information, see how the usertype argument is used in | |||
458 | PyUFunc_RegisterLoopForType(), defined by Numpy at | |||
459 | .../numpy/core/src/umath/ufunc_object.c | |||
460 | */ | |||
461 | for (idx = 0; idx < ufunc->nargs; idx++) { | |||
462 | if (arg_types_arr[idx] >= NPY_USERDEF) { | |||
463 | usertype = arg_types_arr[idx]; | |||
464 | } | |||
465 | } | |||
466 | ||||
467 | if (usertype != NPY_VOID) { | |||
468 | if (PyUFunc_RegisterLoopForType(*(int (*)(PyUFuncObject *, int, PyUFuncGenericFunction, int * , void *)) PyUFunc_API[2])(ufunc, usertype, | |||
469 | (PyUFuncGenericFunction)loop_ptr, | |||
470 | arg_types_arr, data_ptr) < 0) { | |||
471 | goto _dufunc__add_loop_fail; | |||
472 | } | |||
473 | } else if (PyUFunc_ReplaceLoopBySignature(*(int (*)(PyUFuncObject *, PyUFuncGenericFunction, int *, PyUFuncGenericFunction *)) PyUFunc_API[30])(ufunc, | |||
474 | (PyUFuncGenericFunction)loop_ptr, | |||
475 | arg_types_arr, &old_func) == 0) { | |||
476 | /* TODO: Consider freeing any memory held by the old loop (somehow) */ | |||
477 | for (idx = 0; idx < ufunc->ntypes; idx++) { | |||
478 | if (ufunc->functions[idx] == (PyUFuncGenericFunction)loop_ptr) { | |||
479 | ufunc->data[idx] = data_ptr; | |||
480 | break; | |||
481 | } | |||
482 | } | |||
483 | } else { | |||
484 | /* The following is an attempt to loosely follow the allocation | |||
485 | code in Numpy. See ufunc_frompyfunc() in | |||
486 | .../numpy/core/src/umath/umathmodule.c. | |||
487 | ||||
488 | The primary goal is to allocate a single chunk of memory to | |||
489 | hold the functions, data, and types loop arrays: | |||
490 | ||||
491 | ptr == |<- functions ->|<- data ->|<- types ->| | |||
492 | ||||
493 | */ | |||
494 | int ntypes=ufunc->ntypes + 1; | |||
495 | PyUFuncGenericFunction *functions=NULL((void*)0); | |||
496 | void **data=NULL((void*)0); | |||
497 | char *types=NULL((void*)0); | |||
498 | void *newptr=NULL((void*)0), *oldptr=NULL((void*)0); | |||
499 | size_t functions_size=sizeof(PyUFuncGenericFunction) * ntypes; | |||
500 | size_t data_size=sizeof(void *) * ntypes; | |||
501 | size_t type_ofs=sizeof(char) * ufunc->ntypes * ufunc->nargs; | |||
502 | size_t newsize=(functions_size + data_size + | |||
503 | (sizeof(char) * ntypes * ufunc->nargs)); | |||
504 | ||||
505 | oldptr = ufunc->ptr; | |||
506 | newptr = PyArray_mallocPyMem_RawMalloc(newsize); | |||
507 | if (!newptr) { | |||
508 | PyErr_NoMemory(); | |||
509 | goto _dufunc__add_loop_fail; | |||
510 | } | |||
511 | functions = (PyUFuncGenericFunction*)newptr; | |||
512 | memcpy(functions, ufunc->functions, | |||
513 | sizeof(PyUFuncGenericFunction) * ufunc->ntypes); | |||
514 | functions[ntypes - 1] = (PyUFuncGenericFunction)loop_ptr; | |||
515 | data = (void **)((char *)functions + functions_size); | |||
516 | memcpy(data, ufunc->data, sizeof(void *) * ufunc->ntypes); | |||
517 | data[ntypes - 1] = data_ptr; | |||
518 | types = (char *)data + data_size; | |||
519 | memcpy(types, ufunc->types, sizeof(char) * ufunc->ntypes * | |||
520 | ufunc->nargs); | |||
521 | for (idx = 0; idx < ufunc->nargs; idx++) { | |||
522 | types[idx + type_ofs] = (char)arg_types_arr[idx]; | |||
523 | } | |||
524 | ||||
525 | ufunc->ntypes = ntypes; | |||
526 | ufunc->functions = functions; | |||
527 | ufunc->types = types; | |||
528 | ufunc->data = data; | |||
529 | ufunc->ptr = newptr; | |||
530 | PyArray_freePyMem_RawFree(oldptr); | |||
531 | } | |||
532 | ||||
533 | PyArray_freePyMem_RawFree(arg_types_arr); | |||
534 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
535 | return Py_None(&_Py_NoneStruct); | |||
536 | ||||
537 | _dufunc__add_loop_fail: | |||
538 | PyArray_freePyMem_RawFree(arg_types_arr); | |||
539 | return NULL((void*)0); | |||
540 | } | |||
541 | ||||
542 | static struct PyMethodDef dufunc_methods[] = { | |||
543 | {"reduce", | |||
544 | (PyCFunction)dufunc_reduce, | |||
545 | METH_VARARGS0x0001 | METH_KEYWORDS0x0002, NULL((void*)0) }, | |||
546 | {"accumulate", | |||
547 | (PyCFunction)dufunc_accumulate, | |||
548 | METH_VARARGS0x0001 | METH_KEYWORDS0x0002, NULL((void*)0) }, | |||
549 | {"reduceat", | |||
550 | (PyCFunction)dufunc_reduceat, | |||
551 | METH_VARARGS0x0001 | METH_KEYWORDS0x0002, NULL((void*)0) }, | |||
552 | {"outer", | |||
553 | (PyCFunction)dufunc_outer, | |||
554 | METH_VARARGS0x0001 | METH_KEYWORDS0x0002, NULL((void*)0)}, | |||
555 | #if NPY_API_VERSION0x0000000D >= 0x00000008 | |||
556 | {"at", | |||
557 | (PyCFunction)dufunc_at, | |||
558 | METH_VARARGS0x0001, NULL((void*)0)}, | |||
559 | #endif | |||
560 | {"_compile_for_args", | |||
561 | (PyCFunction)dufunc__compile_for_args, | |||
562 | METH_VARARGS0x0001 | METH_KEYWORDS0x0002, | |||
563 | "Abstract method: subclasses should overload _compile_for_args() to compile the ufunc at the given arguments' types."}, | |||
564 | {"_add_loop", | |||
565 | (PyCFunction)dufunc__add_loop, | |||
566 | METH_VARARGS0x0001, | |||
567 | NULL((void*)0)}, | |||
568 | {NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)} /* sentinel */ | |||
569 | }; | |||
570 | ||||
571 | static PyObject * | |||
572 | dufunc_getfrozen(PyDUFuncObject * self, void * closure) | |||
573 | { | |||
574 | PyObject *result=(self->frozen) ? Py_True((PyObject *) &_Py_TrueStruct) : Py_False((PyObject *) &_Py_FalseStruct); | |||
575 | Py_INCREF(result)_Py_INCREF(((PyObject*)(result))); | |||
576 | return result; | |||
577 | } | |||
578 | ||||
579 | static int | |||
580 | dufunc_setfrozen(PyDUFuncObject * self, PyObject * value, void * closure) | |||
581 | { | |||
582 | int result=0; | |||
583 | if (PyObject_IsTrue(value)) { | |||
584 | self->frozen = 1; | |||
585 | } else { | |||
586 | PyErr_SetString(PyExc_ValueError, | |||
587 | "cannot clear the _DUFunc.frozen flag"); | |||
588 | result = -1; | |||
589 | } | |||
590 | return result; | |||
591 | } | |||
592 | ||||
593 | static PyGetSetDef dufunc_getsets[] = { | |||
594 | {"_frozen", | |||
595 | (getter)dufunc_getfrozen, (setter)dufunc_setfrozen, | |||
596 | "flag indicating call-time compilation has been disabled", | |||
597 | NULL((void*)0)}, | |||
598 | {NULL((void*)0)} /* Sentinel */ | |||
599 | }; | |||
600 | ||||
601 | PyTypeObject PyDUFunc_Type = { | |||
602 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | |||
603 | "numba._DUFunc", /* tp_name*/ | |||
604 | sizeof(PyDUFuncObject), /* tp_basicsize*/ | |||
605 | 0, /* tp_itemsize */ | |||
606 | /* methods */ | |||
607 | (destructor) dufunc_dealloc, /* tp_dealloc */ | |||
608 | 0, /* tp_print */ | |||
609 | 0, /* tp_getattr */ | |||
610 | 0, /* tp_setattr */ | |||
611 | 0, /* tp_compare/tp_reserved */ | |||
612 | (reprfunc) dufunc_repr, /* tp_repr */ | |||
613 | 0, /* tp_as_number */ | |||
614 | 0, /* tp_as_sequence */ | |||
615 | 0, /* tp_as_mapping */ | |||
616 | 0, /* tp_hash */ | |||
617 | (ternaryfunc) dufunc_call, /* tp_call */ | |||
618 | (reprfunc) dufunc_repr, /* tp_str */ | |||
619 | 0, /* tp_getattro */ | |||
620 | 0, /* tp_setattro */ | |||
621 | 0, /* tp_as_buffer */ | |||
622 | Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0) | Py_TPFLAGS_BASETYPE(1UL << 10), /* tp_flags */ | |||
623 | 0, /* tp_doc */ | |||
624 | 0, /* tp_traverse */ | |||
625 | 0, /* tp_clear */ | |||
626 | 0, /* tp_richcompare */ | |||
627 | 0, /* tp_weaklistoffset */ | |||
628 | 0, /* tp_iter */ | |||
629 | 0, /* tp_iternext */ | |||
630 | dufunc_methods, /* tp_methods */ | |||
631 | dufunc_members, /* tp_members */ | |||
632 | dufunc_getsets, /* tp_getset */ | |||
633 | 0, /* tp_base */ | |||
634 | 0, /* tp_dict */ | |||
635 | 0, /* tp_descr_get */ | |||
636 | 0, /* tp_descr_set */ | |||
637 | 0, /* tp_dictoffset */ | |||
638 | (initproc) dufunc_init, /* tp_init */ | |||
639 | 0, /* tp_alloc */ | |||
640 | 0, /* tp_new */ | |||
641 | 0, /* tp_free */ | |||
642 | 0, /* tp_is_gc */ | |||
643 | 0, /* tp_bases */ | |||
644 | 0, /* tp_mro */ | |||
645 | 0, /* tp_cache */ | |||
646 | 0, /* tp_subclasses */ | |||
647 | 0, /* tp_weaklist */ | |||
648 | 0, /* tp_del */ | |||
649 | 0, /* tp_version_tag */ | |||
650 | }; | |||
651 | ||||
652 | /* ______________________________________________________________________ | |||
653 | * Module initialization boilerplate follows. | |||
654 | */ | |||
655 | ||||
656 | static PyMethodDef ext_methods[] = { | |||
657 | {"fromfunc", (PyCFunction) ufunc_fromfunc, METH_VARARGS0x0001, NULL((void*)0)}, | |||
658 | { NULL((void*)0) } | |||
659 | }; | |||
660 | ||||
661 | /* Don't remove this marker, it is used for inserting licensing code */ | |||
662 | /*MARK1*/ | |||
663 | ||||
664 | MOD_INIT(_internal)PyObject* PyInit__internal(void) | |||
665 | { | |||
666 | PyObject *m; | |||
667 | ||||
668 | /* Don't remove this marker, it is used for inserting licensing code */ | |||
669 | /*MARK2*/ | |||
670 | ||||
671 | import_array(){if (_import_array() < 0) {PyErr_Print(); PyErr_SetString( PyExc_ImportError, "numpy.core.multiarray failed to import"); return ((void*)0); } }; | |||
| ||||
672 | import_umath()do { if (_import_umath() < 0) { PyErr_Print(); PyErr_SetString (PyExc_ImportError, "numpy.core.umath failed to import"); return ((void*)0); } } while(0); | |||
673 | ||||
674 | MOD_DEF(m, "_internal", "No docs",{ static struct PyModuleDef moduledef = { { { 1, ((void*)0) } , ((void*)0), 0, ((void*)0), }, "_internal", "No docs", -1, ext_methods , ((void*)0), ((void*)0), ((void*)0), ((void*)0) }; m = PyModule_Create2 (&moduledef, 1013); } | |||
| ||||
675 | ext_methods){ static struct PyModuleDef moduledef = { { { 1, ((void*)0) } , ((void*)0), 0, ((void*)0), }, "_internal", "No docs", -1, ext_methods , ((void*)0), ((void*)0), ((void*)0), ((void*)0) }; m = PyModule_Create2 (&moduledef, 1013); } | |||
676 | ||||
677 | if (m == NULL((void*)0)) | |||
678 | return MOD_ERROR_VAL((void*)0); | |||
679 | ||||
680 | if (PyType_Ready(&PyUFuncCleaner_Type) < 0) | |||
681 | return MOD_ERROR_VAL((void*)0); | |||
682 | ||||
683 | PyDUFunc_Type.tp_new = PyType_GenericNew; | |||
684 | if (init_ufunc_dispatch() <= 0) | |||
685 | return MOD_ERROR_VAL((void*)0); | |||
686 | if (PyType_Ready(&PyDUFunc_Type) < 0) | |||
687 | return MOD_ERROR_VAL((void*)0); | |||
688 | Py_INCREF(&PyDUFunc_Type)_Py_INCREF(((PyObject*)(&PyDUFunc_Type))); | |||
689 | if (PyModule_AddObject(m, "_DUFunc", (PyObject *)&PyDUFunc_Type) < 0) | |||
690 | return MOD_ERROR_VAL((void*)0); | |||
691 | ||||
692 | if (PyModule_AddIntMacro(m, PyUFunc_One)PyModule_AddIntConstant(m, "PyUFunc_One", 1) | |||
693 | || PyModule_AddIntMacro(m, PyUFunc_Zero)PyModule_AddIntConstant(m, "PyUFunc_Zero", 0) | |||
694 | || PyModule_AddIntMacro(m, PyUFunc_None)PyModule_AddIntConstant(m, "PyUFunc_None", -1) | |||
695 | #if NPY_API_VERSION0x0000000D >= 0x00000007 | |||
696 | || PyModule_AddIntMacro(m, PyUFunc_ReorderableNone)PyModule_AddIntConstant(m, "PyUFunc_ReorderableNone", -2) | |||
697 | #endif | |||
698 | ) | |||
699 | return MOD_ERROR_VAL((void*)0); | |||
700 | ||||
701 | return MOD_SUCCESS_VAL(m)m; | |||
702 | } | |||
703 | ||||
704 | ||||
705 | #include "_ufunc.c" |
1 | #ifndef PyModule_Create2 |
2 | PyObject* clang_analyzer_PyObject_New_Reference(); |
3 | PyObject* PyModule_Create2(PyModuleDef *def, int module_api_version) { |
4 | return clang_analyzer_PyObject_New_Reference(); |
5 | } |
6 | #else |
7 | #warning "API PyModule_Create2 is defined as a macro." |
8 | #endif |