From 471dde9985d89cfa2442f80753dc639f4908134d Mon Sep 17 00:00:00 2001 From: John Salvatier Date: Mon, 6 Aug 2012 18:11:02 -0700 Subject: gave MapIter an API --- numpy/core/code_generators/cversions.txt | 2 ++ numpy/core/code_generators/genapi.py | 1 + numpy/core/code_generators/numpy_api.py | 4 ++++ numpy/core/setup_common.py | 2 +- numpy/core/src/multiarray/mapping.c | 22 ++++++++++++++++++++-- 5 files changed, 28 insertions(+), 3 deletions(-) (limited to 'numpy') diff --git a/numpy/core/code_generators/cversions.txt b/numpy/core/code_generators/cversions.txt index 5bdb33c94..15d94bd9a 100644 --- a/numpy/core/code_generators/cversions.txt +++ b/numpy/core/code_generators/cversions.txt @@ -11,3 +11,5 @@ 0x00000006 = e61d5dc51fa1c6459328266e215d6987 # Version 7 (NumPy 1.7) improved datetime64, misc utilities. 0x00000007 = e396ba3912dcf052eaee1b0b203a7724 +# Version 8 Added interface to MapIterObject +0x00000008 = 2bd7a9d514b554a38080ab75e8b8e2c4 diff --git a/numpy/core/code_generators/genapi.py b/numpy/core/code_generators/genapi.py index 3860fe6d7..32b0972a7 100644 --- a/numpy/core/code_generators/genapi.py +++ b/numpy/core/code_generators/genapi.py @@ -41,6 +41,7 @@ API_FILES = [join('multiarray', 'array_assign_array.c'), join('multiarray', 'getset.c'), join('multiarray', 'item_selection.c'), join('multiarray', 'iterators.c'), + join('multiarray', 'mapping.c'), join('multiarray', 'methods.c'), join('multiarray', 'multiarraymodule.c'), join('multiarray', 'nditer_api.c'), diff --git a/numpy/core/code_generators/numpy_api.py b/numpy/core/code_generators/numpy_api.py index cb598880b..08c6c1ea1 100644 --- a/numpy/core/code_generators/numpy_api.py +++ b/numpy/core/code_generators/numpy_api.py @@ -71,6 +71,7 @@ multiarray_types_api = { 'PyHalfArrType_Type': 217, 'NpyIter_Type': 218, # End 1.6 API + 'PyArrayMapIter_Type': 295, } #define NPY_NUMUSERTYPES (*(int *)PyArray_API[6]) @@ -330,6 +331,9 @@ multiarray_funcs_api = { 'PyDataMem_FREE': 289, 'PyDataMem_RENEW': 290, 'PyDataMem_SetEventHook': 291, + '_swap_axes': 292, + 'PyArray_MapIterArray': 293, + 'PyArray_MapIterNext': 294, } ufunc_types_api = { diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index 58876a8e4..83589695d 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -29,7 +29,7 @@ C_ABI_VERSION = 0x01000009 # without breaking binary compatibility. In this case, only the C_API_VERSION # (*not* C_ABI_VERSION) would be increased. Whenever binary compatibility is # broken, both C_API_VERSION and C_ABI_VERSION should be increased. -C_API_VERSION = 0x00000007 +C_API_VERSION = 0x00000008 class MismatchCAPIWarning(Warning): pass diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index d414a1fbb..7405bad8e 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -166,7 +166,10 @@ array_ass_big_item(PyArrayObject *self, npy_intp i, PyObject *v) /* -------------------------------------------------------------- */ -static void +/*NUMPY_API + * +*/ +NPY_NO_EXPORT void _swap_axes(PyArrayMapIterObject *mit, PyArrayObject **ret, int getmap) { PyObject *new; @@ -1628,7 +1631,7 @@ PyArray_MapIterReset(PyArrayMapIterObject *mit) return; } -/* +/*NUMPY_API * This function needs to update the state of the map iterator * and point mit->dataptr to the memory-location of the next object */ @@ -2028,6 +2031,21 @@ PyArray_MapIterNew(PyObject *indexobj, int oned, int fancy) return NULL; } +/*NUMPY_API +*/ +NPY_NO_EXPORT PyObject * +PyArray_MapIterArray(PyArrayObject * a, PyObject * index, int oned, int fancy) +{ + PyArrayMapIterObject * mit; + mit = (PyArrayMapIterObject *) PyArray_MapIterNew(index, oned, fancy); + if (mit != NULL) { + PyArray_MapIterBind(mit, a); + PyArray_MapIterReset(mit); + } + return mit; +} + + static void arraymapiter_dealloc(PyArrayMapIterObject *mit) -- cgit v1.2.1 From 860a1f71d0faf267e468f8e09e9903c00910a14e Mon Sep 17 00:00:00 2001 From: John Salvatier Date: Mon, 6 Aug 2012 18:52:04 -0700 Subject: changed the name of _swap_axes --- numpy/core/code_generators/cversions.txt | 2 +- numpy/core/code_generators/numpy_api.py | 4 ++-- numpy/core/src/multiarray/mapping.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'numpy') diff --git a/numpy/core/code_generators/cversions.txt b/numpy/core/code_generators/cversions.txt index 15d94bd9a..7d3b43d3b 100644 --- a/numpy/core/code_generators/cversions.txt +++ b/numpy/core/code_generators/cversions.txt @@ -12,4 +12,4 @@ # Version 7 (NumPy 1.7) improved datetime64, misc utilities. 0x00000007 = e396ba3912dcf052eaee1b0b203a7724 # Version 8 Added interface to MapIterObject -0x00000008 = 2bd7a9d514b554a38080ab75e8b8e2c4 +0x00000008 = 17321775fc884de0b1eda478cd61c74b diff --git a/numpy/core/code_generators/numpy_api.py b/numpy/core/code_generators/numpy_api.py index 08c6c1ea1..64319c166 100644 --- a/numpy/core/code_generators/numpy_api.py +++ b/numpy/core/code_generators/numpy_api.py @@ -71,7 +71,7 @@ multiarray_types_api = { 'PyHalfArrType_Type': 217, 'NpyIter_Type': 218, # End 1.6 API - 'PyArrayMapIter_Type': 295, + 'PyArrayMapIter_Type': 295, } #define NPY_NUMUSERTYPES (*(int *)PyArray_API[6]) @@ -331,7 +331,7 @@ multiarray_funcs_api = { 'PyDataMem_FREE': 289, 'PyDataMem_RENEW': 290, 'PyDataMem_SetEventHook': 291, - '_swap_axes': 292, + 'PyArray_MapIterSwapAxes': 292, 'PyArray_MapIterArray': 293, 'PyArray_MapIterNext': 294, } diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index 7405bad8e..7e67e36dd 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -170,7 +170,7 @@ array_ass_big_item(PyArrayObject *self, npy_intp i, PyObject *v) * */ NPY_NO_EXPORT void -_swap_axes(PyArrayMapIterObject *mit, PyArrayObject **ret, int getmap) +PyArray_MapIterSwapAxes(PyArrayMapIterObject *mit, PyArrayObject **ret, int getmap) { PyObject *new; int n1, n2, n3, val, bnd; @@ -300,7 +300,7 @@ PyArray_GetMap(PyArrayMapIterObject *mit) /* check for consecutive axes */ if ((mit->subspace != NULL) && (mit->consec)) { if (mit->iteraxes[0] > 0) { /* then we need to swap */ - _swap_axes(mit, &ret, 1); + PyArray_MapIterSwapAxes(mit, &ret, 1); } } return (PyObject *)ret; @@ -329,7 +329,7 @@ PyArray_SetMap(PyArrayMapIterObject *mit, PyObject *op) } if ((mit->subspace != NULL) && (mit->consec)) { if (mit->iteraxes[0] > 0) { /* then we need to swap */ - _swap_axes(mit, &arr, 0); + PyArray_MapIterSwapAxes(mit, &arr, 0); if (arr == NULL) { return -1; } -- cgit v1.2.1 From 7c64889c079b21ee1b802f7149698b27d36315e3 Mon Sep 17 00:00:00 2001 From: John Salvatier Date: Fri, 10 Aug 2012 16:21:16 -0700 Subject: removed expsure of mapiter type --- numpy/core/code_generators/numpy_api.py | 1 - 1 file changed, 1 deletion(-) (limited to 'numpy') diff --git a/numpy/core/code_generators/numpy_api.py b/numpy/core/code_generators/numpy_api.py index 64319c166..07e7c8ae5 100644 --- a/numpy/core/code_generators/numpy_api.py +++ b/numpy/core/code_generators/numpy_api.py @@ -71,7 +71,6 @@ multiarray_types_api = { 'PyHalfArrType_Type': 217, 'NpyIter_Type': 218, # End 1.6 API - 'PyArrayMapIter_Type': 295, } #define NPY_NUMUSERTYPES (*(int *)PyArray_API[6]) -- cgit v1.2.1 From 262610140504198b7a1542b65831db78bba50cb8 Mon Sep 17 00:00:00 2001 From: John Salvatier Date: Fri, 10 Aug 2012 16:23:05 -0700 Subject: changed error handling for clarity --- numpy/core/src/multiarray/mapping.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'numpy') diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index 7e67e36dd..6b5b70689 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -2038,10 +2038,12 @@ PyArray_MapIterArray(PyArrayObject * a, PyObject * index, int oned, int fancy) { PyArrayMapIterObject * mit; mit = (PyArrayMapIterObject *) PyArray_MapIterNew(index, oned, fancy); - if (mit != NULL) { - PyArray_MapIterBind(mit, a); - PyArray_MapIterReset(mit); + if (mit == NULL) { + return NULL; } + + PyArray_MapIterBind(mit, a); + PyArray_MapIterReset(mit); return mit; } -- cgit v1.2.1 From 9194042e31301ddd7375e8f3a392e3841b8a4164 Mon Sep 17 00:00:00 2001 From: John Salvatier Date: Mon, 13 Aug 2012 11:46:39 -0700 Subject: eliminated oned and fancy arguments to MapIterArray --- numpy/core/src/multiarray/mapping.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'numpy') diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index 6b5b70689..31446ca41 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -1902,11 +1902,6 @@ PyArray_MapIterNew(PyObject *indexobj, int oned, int fancy) mit->indexobj = indexobj; } -#undef SOBJ_NOTFANCY -#undef SOBJ_ISFANCY -#undef SOBJ_BADARRAY -#undef SOBJ_TOOMANY -#undef SOBJ_LISTTUP if (oned) { return (PyObject *)mit; @@ -2034,9 +2029,16 @@ PyArray_MapIterNew(PyObject *indexobj, int oned, int fancy) /*NUMPY_API */ NPY_NO_EXPORT PyObject * -PyArray_MapIterArray(PyArrayObject * a, PyObject * index, int oned, int fancy) +PyArray_MapIterArray(PyArrayObject * a, PyObject * index) { PyArrayMapIterObject * mit; + int fancy = fancy_indexing_check(index); + int oned = 0; + if (fancy != SOBJ_NOTFANCY) { + + oned = ((PyArray_NDIM(a) == 1) && + !(PyTuple_Check(index) && PyTuple_GET_SIZE(index) > 1)); + } mit = (PyArrayMapIterObject *) PyArray_MapIterNew(index, oned, fancy); if (mit == NULL) { return NULL; @@ -2048,6 +2050,11 @@ PyArray_MapIterArray(PyArrayObject * a, PyObject * index, int oned, int fancy) } +#undef SOBJ_NOTFANCY +#undef SOBJ_ISFANCY +#undef SOBJ_BADARRAY +#undef SOBJ_TOOMANY +#undef SOBJ_LISTTUP static void arraymapiter_dealloc(PyArrayMapIterObject *mit) -- cgit v1.2.1 From f9f949871c04aea7e2463ec7d40ad64f219cd520 Mon Sep 17 00:00:00 2001 From: John Salvatier Date: Mon, 13 Aug 2012 13:08:06 -0700 Subject: added initial mapiter tests --- numpy/core/src/multiarray/multiarray_tests.c.src | 134 +++++++++++++++++++++++ numpy/core/tests/test_multiarray.py | 15 +++ 2 files changed, 149 insertions(+) (limited to 'numpy') diff --git a/numpy/core/src/multiarray/multiarray_tests.c.src b/numpy/core/src/multiarray/multiarray_tests.c.src index 9e46624bf..3250a1bbb 100644 --- a/numpy/core/src/multiarray/multiarray_tests.c.src +++ b/numpy/core/src/multiarray/multiarray_tests.c.src @@ -428,6 +428,137 @@ test_pydatamem_seteventhook_end(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED return Py_None; } + +typedef void (*inplace_map_binop)(PyArrayMapIterObject *, PyArrayIterObject *); + +static void npy_float64_inplace_add(PyArrayMapIterObject *mit, PyArrayIterObject *it) +{ + int index = mit->size; + while (index--) { + ((npy_float64*)mit->dataptr)[0] = ((npy_float64*)mit->dataptr)[0] + ((npy_float64*)it->dataptr)[0]; + + PyArray_MapIterNext(mit); + PyArray_ITER_NEXT(it); + } +} + +inplace_map_binop addition_funcs[] = { +npy_float64_inplace_add, +NULL}; + +int type_numbers[] = { +NPY_FLOAT64, +-1000}; + + + +static int +map_increment(PyArrayMapIterObject *mit, PyObject *op, inplace_map_binop add_inplace) +{ + PyArrayObject *arr = NULL; + PyArrayIterObject *it; + PyArray_Descr *descr; + + if (mit->ait == NULL) { + return -1; + } + descr = PyArray_DESCR(mit->ait->ao); + Py_INCREF(descr); + arr = (PyArrayObject *)PyArray_FromAny(op, descr, + 0, 0, NPY_ARRAY_FORCECAST, NULL); + if (arr == NULL) { + return -1; + } + + if ((mit->subspace != NULL) && (mit->consec)) { + if (mit->iteraxes[0] > 0) { + PyArray_MapIterSwapAxes(mit, (PyArrayObject **)&arr, 0); + if (arr == NULL) { + return -1; + } + } + } + + if ((it = (PyArrayIterObject *)\ + PyArray_BroadcastToShape(arr, mit->dimensions, mit->nd)) == NULL) { + Py_DECREF(arr); + + return -1; + } + + (*add_inplace)(mit, it); + + Py_DECREF(arr); + Py_DECREF(it); + return 0; +} + + +static PyObject * +inplace_increment(PyObject *dummy, PyObject *args) +{ + PyObject *arg_a = NULL, *index=NULL, *inc=NULL; + PyArrayObject *a; + inplace_map_binop add_inplace = NULL; + int type_number = -1; + int i =0; + PyArrayMapIterObject * mit; + + if (!PyArg_ParseTuple(args, "OOO", &arg_a, &index, + &inc)) { + return NULL; + } + if (!PyArray_Check(arg_a)) { + PyErr_SetString(PyExc_ValueError, "needs an ndarray as first argument"); + return NULL; + } + a = (PyArrayObject *) arg_a; + + if (PyArray_FailUnlessWriteable(a, "input/output array") < 0) { + return NULL; + } + + if (PyArray_NDIM(a) == 0) { + PyErr_SetString(PyExc_IndexError, "0-d arrays can't be indexed."); + return NULL; + } + type_number = PyArray_TYPE(a); + + + + + while (type_numbers[i] >= 0 && addition_funcs[i] != NULL){ + if (type_number == type_numbers[i]) { + add_inplace = addition_funcs[i]; + break; + } + i++ ; + } + + if (add_inplace == NULL) { + PyErr_SetString(PyExc_TypeError, "unsupported type for a"); + return NULL; + } + + mit = (PyArrayMapIterObject *) PyArray_MapIterArray(a, index); + if (mit == NULL) { + goto fail; + } + + if (map_increment(mit, inc, add_inplace) != 0) { + goto fail; + } + + Py_DECREF(mit); + + Py_INCREF(Py_None); + return Py_None; + +fail: + Py_XDECREF(mit); + + return NULL; +} static PyMethodDef Multiarray_TestsMethods[] = { {"test_neighborhood_iterator", test_neighborhood_iterator, @@ -441,6 +572,9 @@ static PyMethodDef Multiarray_TestsMethods[] = { {"test_pydatamem_seteventhook_end", test_pydatamem_seteventhook_end, METH_NOARGS, NULL}, + {"test_increment_inplace", + inplace_increment, + METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} /* Sentinel */ }; diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index e554d79fc..21b809b52 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -2837,6 +2837,21 @@ class TestMemEventHook(TestCase): del a test_pydatamem_seteventhook_end() +class TestMapIter(TestCase): + def test_mapiter(self): + # The actual tests are within the C code in + # multiarray/multiarray_tests.c.src + + a = arange(12).reshape((3,4)).astype(float) + index = ([1,1,2,0], [0,0,2,3]) + vals = [50,50, 30,16] + + inplace_increment(a, index, vals) + assert_equal(a, [[ 0. , 1., 2., 19.,], + [ 104., 5., 6., 7.,], + [ 8., 9., 40., 11.,]]) + + if __name__ == "__main__": run_module_suite() -- cgit v1.2.1 From d05d9994f7345ee3de599a2e27b830ff192f90ff Mon Sep 17 00:00:00 2001 From: John Salvatier Date: Sun, 7 Oct 2012 09:54:41 -0700 Subject: fixed tests --- numpy/core/src/multiarray/multiarray_tests.c.src | 2 +- numpy/core/tests/test_multiarray.py | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'numpy') diff --git a/numpy/core/src/multiarray/multiarray_tests.c.src b/numpy/core/src/multiarray/multiarray_tests.c.src index 3250a1bbb..954097e28 100644 --- a/numpy/core/src/multiarray/multiarray_tests.c.src +++ b/numpy/core/src/multiarray/multiarray_tests.c.src @@ -572,7 +572,7 @@ static PyMethodDef Multiarray_TestsMethods[] = { {"test_pydatamem_seteventhook_end", test_pydatamem_seteventhook_end, METH_NOARGS, NULL}, - {"test_increment_inplace", + {"test_inplace_increment", inplace_increment, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} /* Sentinel */ diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 21b809b52..62494535f 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -2843,13 +2843,14 @@ class TestMapIter(TestCase): # multiarray/multiarray_tests.c.src a = arange(12).reshape((3,4)).astype(float) - index = ([1,1,2,0], [0,0,2,3]) - vals = [50,50, 30,16] - - inplace_increment(a, index, vals) - assert_equal(a, [[ 0. , 1., 2., 19.,], - [ 104., 5., 6., 7.,], - [ 8., 9., 40., 11.,]]) + index = ([1,1,2,0], + [0,0,2,3]) + vals = [50,50, 30,16] + + inplace_increment(a, index, vals) + assert_equal(a, [[ 0. , 1., 2., 19.,], + [ 104., 5., 6., 7.,], + [ 8., 9., 40., 11.,]]) -- cgit v1.2.1 From 65bd91defe76f225d27b58a21a89dc5dcf7c53c2 Mon Sep 17 00:00:00 2001 From: John Salvatier Date: Sun, 7 Oct 2012 10:17:18 -0700 Subject: inplace passes tests --- numpy/core/code_generators/numpy_api.py | 6 +++--- numpy/core/tests/test_multiarray.py | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'numpy') diff --git a/numpy/core/code_generators/numpy_api.py b/numpy/core/code_generators/numpy_api.py index 07e7c8ae5..16278f1a2 100644 --- a/numpy/core/code_generators/numpy_api.py +++ b/numpy/core/code_generators/numpy_api.py @@ -330,9 +330,9 @@ multiarray_funcs_api = { 'PyDataMem_FREE': 289, 'PyDataMem_RENEW': 290, 'PyDataMem_SetEventHook': 291, - 'PyArray_MapIterSwapAxes': 292, - 'PyArray_MapIterArray': 293, - 'PyArray_MapIterNext': 294, + 'PyArray_MapIterSwapAxes': 293, + 'PyArray_MapIterArray': 294, + 'PyArray_MapIterNext': 295, } ufunc_types_api = { diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 62494535f..5b3f0de0e 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -12,6 +12,7 @@ from test_print import in_foreign_locale from numpy.core.multiarray_tests import ( test_neighborhood_iterator, test_neighborhood_iterator_oob, test_pydatamem_seteventhook_start, test_pydatamem_seteventhook_end, + test_inplace_increment ) from numpy.testing import ( TestCase, run_module_suite, assert_, assert_raises, @@ -2847,7 +2848,7 @@ class TestMapIter(TestCase): [0,0,2,3]) vals = [50,50, 30,16] - inplace_increment(a, index, vals) + test_inplace_increment(a, index, vals) assert_equal(a, [[ 0. , 1., 2., 19.,], [ 104., 5., 6., 7.,], [ 8., 9., 40., 11.,]]) -- cgit v1.2.1