| 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 |