diff options
| author | Julian Taylor <jtaylor.debian@googlemail.com> | 2014-07-18 21:31:44 +0200 |
|---|---|---|
| committer | Julian Taylor <jtaylor.debian@googlemail.com> | 2014-07-18 21:48:14 +0200 |
| commit | c09d0ce0e11c94a83413c1bc6c9b2f5f40008a5a (patch) | |
| tree | 465ee903d43308c02e8968fa1bcb19a1c4e8faec /numpy/core | |
| parent | 88cf0e4f6d722b12f2d57e3acb6452d6a015cc93 (diff) | |
| download | numpy-c09d0ce0e11c94a83413c1bc6c9b2f5f40008a5a.tar.gz | |
BUG: initialize object array of array on resize and zeros
np.zeros(2, dtype=[('k', object, 2)]) did only initialize the first
element to zero while the rest stayed None.
In [1]: numpy.zeros(2, dtype=[('k', object, 2)])
Out[1]:
array([([0, None],), ([0, None],)],
dtype=[('k', 'O', (2,))])
This is a surprising and likely not intended behavior which is fixed
here.
The changed function PyArray_FillObjectArray is only used with None or
zero inputs from numpy, though as its part of the API it could affect
third parties but this is not very likely.
Additionally the memory after the first element was not initialized when
the object was resized.
Closes gh-4857
Diffstat (limited to 'numpy/core')
| -rw-r--r-- | numpy/core/src/multiarray/refcount.c | 8 | ||||
| -rw-r--r-- | numpy/core/src/multiarray/shape.c | 8 | ||||
| -rw-r--r-- | numpy/core/tests/test_multiarray.py | 12 |
3 files changed, 24 insertions, 4 deletions
diff --git a/numpy/core/src/multiarray/refcount.c b/numpy/core/src/multiarray/refcount.c index eab11e933..88f660118 100644 --- a/numpy/core/src/multiarray/refcount.c +++ b/numpy/core/src/multiarray/refcount.c @@ -275,8 +275,12 @@ _fillobject(char *optr, PyObject *obj, PyArray_Descr *dtype) } } else { - Py_XINCREF(obj); - NPY_COPY_PYOBJECT_PTR(optr, &obj); + npy_intp i; + for (i = 0; i < dtype->elsize / sizeof(obj); i++) { + Py_XINCREF(obj); + NPY_COPY_PYOBJECT_PTR(optr, &obj); + optr += sizeof(obj); + } return; } } diff --git a/numpy/core/src/multiarray/shape.c b/numpy/core/src/multiarray/shape.c index d5fde5b97..2278b5d5b 100644 --- a/numpy/core/src/multiarray/shape.c +++ b/numpy/core/src/multiarray/shape.c @@ -326,8 +326,12 @@ _putzero(char *optr, PyObject *zero, PyArray_Descr *dtype) } } else { - Py_INCREF(zero); - NPY_COPY_PYOBJECT_PTR(optr, &zero); + npy_intp i; + for (i = 0; i < dtype->elsize / sizeof(zero); i++) { + Py_INCREF(zero); + NPY_COPY_PYOBJECT_PTR(optr, &zero); + optr += sizeof(zero); + } } return; } diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 2e40a2b7c..9c51895fa 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -511,6 +511,10 @@ class TestCreation(TestCase): assert_array_equal(d, [0] * 13) assert_equal(np.count_nonzero(d), 0) + def test_zeros_obj_obj(self): + d = zeros(10, dtype=[('k', object, 2)]) + assert_array_equal(d['k'], 0) + def test_sequence_non_homogenous(self): assert_equal(np.array([4, 2**80]).dtype, np.object) assert_equal(np.array([4, 2**80, 4]).dtype, np.object) @@ -2784,6 +2788,14 @@ class TestResize(TestCase): assert_array_equal(x[0], np.eye(3)) assert_array_equal(x[1], np.zeros((3, 3))) + def test_obj_obj(self): + # check memory is initialized on resize, gh-4857 + a = ones(10, dtype=[('k', object, 2)]) + a.resize(15,) + assert_equal(a.shape, (15,)) + assert_array_equal(a['k'][-5:], 0) + assert_array_equal(a['k'][:-5], 1) + class TestRecord(TestCase): def test_field_rename(self): |
