diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2017-03-04 12:38:44 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-04 12:38:44 -0700 |
commit | 8d85989a1c269ecd18f2aec697ab38da96ed5307 (patch) | |
tree | 810135c98e7c74b0ced5b34581d851a2d6dfed3d | |
parent | e50b4cbd80fa83b66819af9a57a935aea0d216b3 (diff) | |
parent | 91374d117e1dea50467a14c0d697690ee9630c1b (diff) | |
download | numpy-8d85989a1c269ecd18f2aec697ab38da96ed5307.tar.gz |
Merge pull request #8739 from charris/backports-1.12.1
BUG: Backport bug fixes for 1.12.1
-rw-r--r-- | numpy/core/numeric.py | 10 | ||||
-rw-r--r-- | numpy/core/src/multiarray/methods.c | 57 | ||||
-rw-r--r-- | numpy/core/src/umath/ufunc_object.c | 4 | ||||
-rw-r--r-- | numpy/core/tests/test_numeric.py | 12 | ||||
-rw-r--r-- | numpy/core/tests/test_regression.py | 7 | ||||
-rw-r--r-- | numpy/core/tests/test_umath.py | 13 | ||||
-rwxr-xr-x | numpy/f2py/crackfortran.py | 3 | ||||
-rw-r--r-- | numpy/ma/core.py | 31 | ||||
-rw-r--r-- | numpy/ma/tests/test_core.py | 10 |
9 files changed, 96 insertions, 51 deletions
diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index b90b0a9c9..5a8b92a4f 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -2212,7 +2212,7 @@ def binary_repr(num, width=None): designated form. If the `width` value is insufficient, it will be ignored, and `num` will - be returned in binary(`num` > 0) or two's complement (`num` < 0) form + be returned in binary (`num` > 0) or two's complement (`num` < 0) form with its width equal to the minimum number of bits needed to represent the number in the designated form. This behavior is deprecated and will later raise an error. @@ -2282,10 +2282,16 @@ def binary_repr(num, width=None): else: poswidth = len(bin(-num)[2:]) - twocomp = 2**(poswidth + 1) + num + # See gh-8679: remove extra digit + # for numbers at boundaries. + if 2**(poswidth - 1) == -num: + poswidth -= 1 + + twocomp = 2**(poswidth + 1) + num binary = bin(twocomp)[2:] binwidth = len(binary) + outwidth = max(binwidth, width) warn_if_insufficient(width, binwidth) return '1' * (outwidth - binwidth) + binary diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c index f2e1d87ad..80d4aebeb 100644 --- a/numpy/core/src/multiarray/methods.c +++ b/numpy/core/src/multiarray/methods.c @@ -1441,41 +1441,42 @@ array_deepcopy(PyArrayObject *self, PyObject *args) Py_DECREF(copied_array); return NULL; } - iter = (NpyIter *)NpyIter_New(copied_array, - (NPY_ITER_READWRITE | - NPY_ITER_EXTERNAL_LOOP | - NPY_ITER_REFS_OK), - NPY_KEEPORDER, - NPY_NO_CASTING, - NULL); + iter = NpyIter_New(copied_array, + NPY_ITER_READWRITE | + NPY_ITER_EXTERNAL_LOOP | + NPY_ITER_REFS_OK | + NPY_ITER_ZEROSIZE_OK, + NPY_KEEPORDER, NPY_NO_CASTING, + NULL); if (iter == NULL) { Py_DECREF(deepcopy); Py_DECREF(copied_array); return NULL; } - iternext = NpyIter_GetIterNext(iter, NULL); - if (iternext == NULL) { - NpyIter_Deallocate(iter); - Py_DECREF(deepcopy); - Py_DECREF(copied_array); - return NULL; - } - - dataptr = NpyIter_GetDataPtrArray(iter); - strideptr = NpyIter_GetInnerStrideArray(iter); - innersizeptr = NpyIter_GetInnerLoopSizePtr(iter); - - do { - data = *dataptr; - stride = *strideptr; - count = *innersizeptr; - while (count--) { - _deepcopy_call(data, data, PyArray_DESCR(copied_array), - deepcopy, visit); - data += stride; + if (NpyIter_GetIterSize(iter) != 0) { + iternext = NpyIter_GetIterNext(iter, NULL); + if (iternext == NULL) { + NpyIter_Deallocate(iter); + Py_DECREF(deepcopy); + Py_DECREF(copied_array); + return NULL; } - } while (iternext(iter)); + dataptr = NpyIter_GetDataPtrArray(iter); + strideptr = NpyIter_GetInnerStrideArray(iter); + innersizeptr = NpyIter_GetInnerLoopSizePtr(iter); + + do { + data = *dataptr; + stride = *strideptr; + count = *innersizeptr; + while (count--) { + _deepcopy_call(data, data, PyArray_DESCR(copied_array), + deepcopy, visit); + data += stride; + } + } while (iternext(iter)); + } NpyIter_Deallocate(iter); Py_DECREF(deepcopy); } diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index 62024d2e3..69fb255fa 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -4395,6 +4395,7 @@ ufunc_generic_call(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds) continue; } res = PyObject_CallFunction(wrap, "O(OOi)", mps[j], ufunc, args, i); + /* Handle __array_wrap__ that does not accept a context argument */ if (res == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) { PyErr_Clear(); res = PyObject_CallFunctionObjArgs(wrap, mps[j], NULL); @@ -4403,9 +4404,6 @@ ufunc_generic_call(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds) if (res == NULL) { goto fail; } - else if (res == Py_None) { - Py_DECREF(res); - } else { Py_DECREF(mps[j]); retobj[i] = res; diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py index c31e9e07c..28b58e358 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -1149,6 +1149,18 @@ class TestBinaryRepr(TestCase): assert_equal(np.binary_repr(10, width=7), '0001010') assert_equal(np.binary_repr(-5, width=7), '1111011') + def test_neg_width_boundaries(self): + # see gh-8670 + + # Ensure that the example in the issue does not + # break before proceeding to a more thorough test. + assert_equal(np.binary_repr(-128, width=8), '10000000') + + for width in range(1, 11): + num = -2**(width - 1) + exp = '1' + (width - 1) * '0' + assert_equal(np.binary_repr(num, width=width), exp) + class TestBaseRepr(TestCase): def test_base3(self): diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 721a025de..4875f852a 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -2094,6 +2094,13 @@ class TestRegression(TestCase): # Check the references hold for the copied objects. self.assertTrue(arr_cp[0, 1] is arr_cp[1, 1]) + def test_deepcopy_empty_object_array(self): + # Ticket #8536. + # Deepcopy should succeed + a = np.array([], dtype=object) + b = copy.deepcopy(a) + assert_(a.shape == b.shape) + def test_bool_subscript_crash(self): # gh-4494 c = np.rec.array([(1, 2, 3), (4, 5, 6)]) diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index 4c0243559..6fea832c9 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -1379,6 +1379,19 @@ class TestSpecialMethods(TestCase): a = A() self.assertRaises(RuntimeError, ncu.maximum, a, a) + def test_none_wrap(self): + # Tests that issue #8507 is resolved. Previously, this would segfault + + class A(object): + def __array__(self): + return np.zeros(1) + + def __array_wrap__(self, arr, context=None): + return None + + a = A() + assert_equal(ncu.maximum(a, a), None) + def test_default_prepare(self): class with_wrap(object): diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index e38e8e3fe..f738a9f00 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -2392,7 +2392,8 @@ def _selected_real_kind_func(p, r=0, radix=0): return 4 if p < 16: return 8 - if platform.machine().lower().startswith('power'): + machine = platform.machine().lower() + if machine.startswith('power') or machine.startswith('ppc64'): if p <= 20: return 16 else: diff --git a/numpy/ma/core.py b/numpy/ma/core.py index 73f39fce1..847c78a20 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -6384,21 +6384,16 @@ class _frommethod: def __call__(self, a, *args, **params): if self.reversed: args = list(args) - arr = args[0] - args[0] = a - a = arr - # Get the method from the array (if possible) + a, args[0] = args[0], a + + marr = asanyarray(a) method_name = self.__name__ - method = getattr(a, method_name, None) - if method is not None: - return method(*args, **params) - # Still here ? Then a is not a MaskedArray - method = getattr(MaskedArray, method_name, None) - if method is not None: - return method(MaskedArray(a), *args, **params) - # Still here ? OK, let's call the corresponding np function - method = getattr(np, method_name) - return method(a, *args, **params) + method = getattr(type(marr), method_name, None) + if method is None: + # use the corresponding np function + method = getattr(np, method_name) + + return method(marr, *args, **params) all = _frommethod('all') @@ -6547,9 +6542,7 @@ def compressed(x): Equivalent method. """ - if not isinstance(x, MaskedArray): - x = asanyarray(x) - return x.compressed() + return asanyarray(x).compressed() def concatenate(arrays, axis=0): @@ -7695,6 +7688,10 @@ def asanyarray(a, dtype=None): <class 'numpy.ma.core.MaskedArray'> """ + # workaround for #8666, to preserve identity. Ideally the bottom line + # would handle this for us. + if isinstance(a, MaskedArray) and (dtype is None or dtype == a.dtype): + return a return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True) diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py index 5a1ed2be8..4df48a2b0 100644 --- a/numpy/ma/tests/test_core.py +++ b/numpy/ma/tests/test_core.py @@ -433,6 +433,11 @@ class TestMaskedArray(TestCase): assert_not_equal(y._data.ctypes.data, x._data.ctypes.data) assert_not_equal(y._mask.ctypes.data, x._mask.ctypes.data) + def test_copy_on_python_builtins(self): + # Tests copy works on python builtins (issue#8019) + self.assertTrue(isMaskedArray(np.ma.copy([1,2,3]))) + self.assertTrue(isMaskedArray(np.ma.copy((1,2,3)))) + def test_copy_immutable(self): # Tests that the copy method is immutable, GitHub issue #5247 a = np.ma.array([1, 2, 3]) @@ -1032,6 +1037,11 @@ class TestMaskedArrayArithmetic(TestCase): assert_(res.dtype.type is np.intp) assert_raises(ValueError, ott.count, axis=1) + def test_count_on_python_builtins(self): + # Tests count works on python builtins (issue#8019) + assert_equal(3, count([1,2,3])) + assert_equal(2, count((1,2))) + def test_minmax_func(self): # Tests minimum and maximum. (x, y, a10, m1, m2, xm, ym, z, zm, xf) = self.d |