summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2017-03-04 12:38:44 -0700
committerGitHub <noreply@github.com>2017-03-04 12:38:44 -0700
commit8d85989a1c269ecd18f2aec697ab38da96ed5307 (patch)
tree810135c98e7c74b0ced5b34581d851a2d6dfed3d
parente50b4cbd80fa83b66819af9a57a935aea0d216b3 (diff)
parent91374d117e1dea50467a14c0d697690ee9630c1b (diff)
downloadnumpy-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.py10
-rw-r--r--numpy/core/src/multiarray/methods.c57
-rw-r--r--numpy/core/src/umath/ufunc_object.c4
-rw-r--r--numpy/core/tests/test_numeric.py12
-rw-r--r--numpy/core/tests/test_regression.py7
-rw-r--r--numpy/core/tests/test_umath.py13
-rwxr-xr-xnumpy/f2py/crackfortran.py3
-rw-r--r--numpy/ma/core.py31
-rw-r--r--numpy/ma/tests/test_core.py10
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