summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/include/numpy/ufuncobject.h8
-rw-r--r--numpy/core/src/umath/ufunc_object.c48
-rw-r--r--numpy/core/src/umath/umathmodule.c1
3 files changed, 47 insertions, 10 deletions
diff --git a/numpy/core/include/numpy/ufuncobject.h b/numpy/core/include/numpy/ufuncobject.h
index 90d837a9b..15dcdf010 100644
--- a/numpy/core/include/numpy/ufuncobject.h
+++ b/numpy/core/include/numpy/ufuncobject.h
@@ -120,7 +120,11 @@ typedef struct _tagPyUFuncObject {
*/
int nin, nout, nargs;
- /* Identity for reduction, either PyUFunc_One or PyUFunc_Zero */
+ /*
+ * Identity for reduction, any of PyUFunc_One, PyUFunc_Zero
+ * PyUFunc_MinusOne, PyUFunc_None, PyUFunc_ReorderableNone,
+ * PyUFunc_IdentityValue.
+ */
int identity;
/* Array of one-dimensional core loops */
@@ -301,7 +305,7 @@ typedef struct _tagPyUFuncObject {
*/
#define PyUFunc_ReorderableNone -2
/*
- * UFunc unit is in identity_value, and the order of operations can be reordered
+ * UFunc unit is an identity_value, and the order of operations can be reordered
* This case allows reduction with multiple axes at once.
*/
#define PyUFunc_IdentityValue -3
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index ac641c610..ab986caa1 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -4928,12 +4928,15 @@ PyUFunc_FromFuncAndDataAndSignatureAndIdentity(PyUFuncGenericFunction *func, voi
return NULL;
}
- ufunc = PyArray_malloc(sizeof(PyUFuncObject));
+ ufunc = PyObject_GC_New(PyUFuncObject, &PyUFunc_Type);
+ /*
+ * We use GC_New here for ufunc->obj, but do not use GC_Track since
+ * ufunc->obj is still NULL at the end of this function.
+ * See ufunc_frompyfunc where ufunc->obj is set and GC_Track is called.
+ */
if (ufunc == NULL) {
return NULL;
}
- memset(ufunc, 0, sizeof(PyUFuncObject));
- PyObject_Init((PyObject *)ufunc, &PyUFunc_Type);
ufunc->nin = nin;
ufunc->nout = nout;
@@ -4941,13 +4944,30 @@ PyUFunc_FromFuncAndDataAndSignatureAndIdentity(PyUFuncGenericFunction *func, voi
ufunc->identity = identity;
if (ufunc->identity == PyUFunc_IdentityValue) {
Py_INCREF(identity_value);
+ ufunc->identity_value = identity_value;
+ }
+ else {
+ ufunc->identity_value = NULL;
}
- ufunc->identity_value = identity_value;
ufunc->functions = func;
ufunc->data = data;
ufunc->types = types;
ufunc->ntypes = ntypes;
+ ufunc->core_signature = NULL;
+ ufunc->core_enabled = 0;
+ ufunc->obj = NULL;
+ ufunc->core_num_dims = NULL;
+ ufunc->core_num_dim_ix = 0;
+ ufunc->core_offsets = NULL;
+ ufunc->core_dim_ixs = NULL;
+ ufunc->core_dim_sizes = NULL;
+ ufunc->core_dim_flags = NULL;
+ ufunc->userloops = NULL;
+ ufunc->ptr = NULL;
+ ufunc->reserved2 = NULL;
+ ufunc->reserved1 = 0;
+ ufunc->iter_flags = 0;
/* Type resolution and inner loop selection functions */
ufunc->type_resolver = &PyUFunc_DefaultTypeResolver;
@@ -5313,6 +5333,7 @@ PyUFunc_RegisterLoopForType(PyUFuncObject *ufunc,
static void
ufunc_dealloc(PyUFuncObject *ufunc)
{
+ PyObject_GC_UnTrack((PyObject *)ufunc);
PyArray_free(ufunc->core_num_dims);
PyArray_free(ufunc->core_dim_ixs);
PyArray_free(ufunc->core_dim_sizes);
@@ -5322,11 +5343,13 @@ ufunc_dealloc(PyUFuncObject *ufunc)
PyArray_free(ufunc->ptr);
PyArray_free(ufunc->op_flags);
Py_XDECREF(ufunc->userloops);
- Py_XDECREF(ufunc->obj);
if (ufunc->identity == PyUFunc_IdentityValue) {
Py_DECREF(ufunc->identity_value);
}
- PyArray_free(ufunc);
+ if (ufunc->obj != NULL) {
+ Py_DECREF(ufunc->obj);
+ }
+ PyObject_GC_Del(ufunc);
}
static PyObject *
@@ -5335,6 +5358,15 @@ ufunc_repr(PyUFuncObject *ufunc)
return PyUString_FromFormat("<ufunc '%s'>", ufunc->name);
}
+static int
+ufunc_traverse(PyUFuncObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->obj);
+ if (self->identity == PyUFunc_IdentityValue) {
+ Py_VISIT(self->identity_value);
+ }
+ return 0;
+}
/******************************************************************************
*** UFUNC METHODS ***
@@ -6051,9 +6083,9 @@ NPY_NO_EXPORT PyTypeObject PyUFunc_Type = {
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)ufunc_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
diff --git a/numpy/core/src/umath/umathmodule.c b/numpy/core/src/umath/umathmodule.c
index 4d3151328..23e3ffcfc 100644
--- a/numpy/core/src/umath/umathmodule.c
+++ b/numpy/core/src/umath/umathmodule.c
@@ -161,6 +161,7 @@ ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *NPY_UNUS
self->type_resolver = &object_ufunc_type_resolver;
self->legacy_inner_loop_selector = &object_ufunc_loop_selector;
+ PyObject_GC_Track(self);
return (PyObject *)self;
}