|
34 | 34 | }\ |
35 | 35 | } while (0) |
36 | 36 |
|
37 | | -// Placeholder of not implemented functions. |
38 | | -# define AK_NOT_IMPLEMENTED\ |
| 37 | +// Placeholder of not implemented pathways / debugging. |
| 38 | +# define AK_NOT_IMPLEMENTED(msg)\ |
39 | 39 | do {\ |
40 | | - PyErr_SetNone(PyExc_NotImplementedError);\ |
| 40 | + PyErr_SetString(PyExc_NotImplementedError, msg);\ |
41 | 41 | return NULL;\ |
42 | 42 | } while (0) |
43 | 43 |
|
@@ -148,6 +148,65 @@ AK_ResolveDTypeIter(PyObject *dtypes) |
148 | 148 | return resolved; |
149 | 149 | } |
150 | 150 |
|
| 151 | +// Numpy implementation: https://github.com/numpy/numpy/blob/a14c41264855e44ebd6187d7541b5b8d59bb32cb/numpy/core/src/multiarray/methods.c#L1557 |
| 152 | +PyObject* |
| 153 | +AK_ArrayDeepCopy(PyArrayObject *array, PyObject *memo) |
| 154 | +{ |
| 155 | + PyObject *id = PyLong_FromVoidPtr((PyObject*)array); |
| 156 | + if (!id) { |
| 157 | + return NULL; |
| 158 | + } |
| 159 | + PyObject *found = PyDict_GetItemWithError(memo, id); |
| 160 | + if (found) { // found will be NULL if not in dict |
| 161 | + Py_INCREF(found); // got a borrowed ref, increment first |
| 162 | + Py_DECREF(id); |
| 163 | + return found; |
| 164 | + } |
| 165 | + else if (PyErr_Occurred()) { |
| 166 | + goto error; |
| 167 | + } |
| 168 | + |
| 169 | + // if dtype is object, call deepcopy with memo |
| 170 | + PyObject *array_new; |
| 171 | + PyArray_Descr *dtype = PyArray_DESCR(array); // borrowed ref |
| 172 | + |
| 173 | + if (PyDataType_ISOBJECT(dtype)) { |
| 174 | + PyObject *copy = PyImport_ImportModule("copy"); |
| 175 | + if (!copy) { |
| 176 | + goto error; |
| 177 | + } |
| 178 | + PyObject *deepcopy = PyObject_GetAttrString(copy, "deepcopy"); |
| 179 | + Py_DECREF(copy); |
| 180 | + if (!deepcopy) { |
| 181 | + goto error; |
| 182 | + } |
| 183 | + array_new = PyObject_CallFunctionObjArgs(deepcopy, array, memo, NULL); |
| 184 | + Py_DECREF(deepcopy); |
| 185 | + if (!array_new) { |
| 186 | + goto error; |
| 187 | + } |
| 188 | + } |
| 189 | + else { |
| 190 | + Py_INCREF(dtype); // PyArray_FromArray steals a reference |
| 191 | + array_new = PyArray_FromArray( |
| 192 | + array, |
| 193 | + dtype, |
| 194 | + NPY_ARRAY_ENSURECOPY); |
| 195 | + if (!array_new || PyDict_SetItem(memo, id, array_new)) { |
| 196 | + Py_XDECREF(array_new); |
| 197 | + goto error; |
| 198 | + } |
| 199 | + } |
| 200 | + // set immutable |
| 201 | + PyArray_CLEARFLAGS((PyArrayObject *)array_new, NPY_ARRAY_WRITEABLE); |
| 202 | + Py_DECREF(id); |
| 203 | + return array_new; |
| 204 | +error: |
| 205 | + Py_DECREF(id); |
| 206 | + return NULL; |
| 207 | +} |
| 208 | + |
| 209 | + |
151 | 210 | //------------------------------------------------------------------------------ |
152 | 211 | // AK module public methods |
153 | 212 | //------------------------------------------------------------------------------ |
@@ -249,6 +308,26 @@ row_1d_filter(PyObject *Py_UNUSED(m), PyObject *a) |
249 | 308 | return a; |
250 | 309 | } |
251 | 310 |
|
| 311 | +//------------------------------------------------------------------------------ |
| 312 | +// array utility |
| 313 | + |
| 314 | +// Specialized array deepcopy that stores immutable arrays in memo dict. |
| 315 | +static PyObject * |
| 316 | +array_deepcopy(PyObject *Py_UNUSED(m), PyObject *args) |
| 317 | +{ |
| 318 | + PyObject *array, *memo; |
| 319 | + if (!PyArg_UnpackTuple(args, "array_deepcopy", 2, 2, &array, &memo)) { |
| 320 | + return NULL; |
| 321 | + } |
| 322 | + AK_CHECK_NUMPY_ARRAY(array); |
| 323 | + if (!PyDict_CheckExact(memo)) { |
| 324 | + PyErr_Format(PyExc_TypeError, "expected a dict (got %s)", |
| 325 | + Py_TYPE(memo)->tp_name); |
| 326 | + return NULL; |
| 327 | + } |
| 328 | + return AK_ArrayDeepCopy((PyArrayObject*)array, memo); |
| 329 | +} |
| 330 | + |
252 | 331 | //------------------------------------------------------------------------------ |
253 | 332 | // type resolution |
254 | 333 |
|
@@ -544,6 +623,7 @@ static PyMethodDef arraykit_methods[] = { |
544 | 623 | {"column_2d_filter", column_2d_filter, METH_O, NULL}, |
545 | 624 | {"column_1d_filter", column_1d_filter, METH_O, NULL}, |
546 | 625 | {"row_1d_filter", row_1d_filter, METH_O, NULL}, |
| 626 | + {"array_deepcopy", array_deepcopy, METH_VARARGS, NULL}, |
547 | 627 | {"resolve_dtype", resolve_dtype, METH_VARARGS, NULL}, |
548 | 628 | {"resolve_dtype_iter", resolve_dtype_iter, METH_O, NULL}, |
549 | 629 | {NULL}, |
|
0 commit comments