Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

BUG: Fix boolean indexing to previous behavior by adding an additiona…

…l check before using the new code path. Add tests.
  • Loading branch information...
commit db1701baf57965e8533293426a0c3b403e81f39a 1 parent 134174c
@teoliphant teoliphant authored
View
14 doc/release/2.0.0-notes.rst
@@ -24,12 +24,9 @@ The default casting rule for UFunc out= parameters has been changed from
rule are likely bugs, so this change may expose previously undetected
errors in projects that depend on NumPy.
-Full-array boolean indexing used to allow boolean arrays with a size
-non-broadcastable to the array size. Now it forces this to be broadcastable.
-Since this affects some legacy code, this change will require discussion
-during alpha or early beta testing, and a decision to either keep the
-stricter behavior, or add in a hack to allow the previous behavior to
-work.
+Full-array boolean indexing has been optimized to use a different,
+optimized code path. This code path should produce the same results,
+but any feedback about changes to your code would be appreciated.
Attempting to write to a read-only array (one with
``arr.flags.writeable`` set to ``False``) used to raise either a
@@ -42,6 +39,11 @@ performance. Because of the nature of floating-point arithmetic, this
may subtly change some results, just as linking NumPy to a different
BLAS implementations such as MKL can.
+If upgrading from 1.5, then generally in 1.6 and 1.7 there have been
+substantial code added and some code paths altered, particularly in
+the areas of type resolution and buffered iteration over universal
+functions. This might have an impact on your code particularly if
+you relied on accidental behavior in the past.
New features
============
View
7 numpy/core/src/multiarray/mapping.c
@@ -1023,8 +1023,10 @@ array_subscript(PyArrayObject *self, PyObject *op)
}
/* Boolean indexing special case */
+ /* The SIZE check might be overly cautious */
if (PyArray_Check(op) && (PyArray_TYPE((PyArrayObject *)op) == NPY_BOOL)
- && (PyArray_NDIM(self) == PyArray_NDIM((PyArrayObject *)op))) {
+ && (PyArray_NDIM(self) == PyArray_NDIM((PyArrayObject *)op))
+ && (PyArray_SIZE((PyArrayObject *)op) == PyArray_SIZE(self))) {
return (PyObject *)array_boolean_subscript(self,
(PyArrayObject *)op, NPY_CORDER);
}
@@ -1269,7 +1271,8 @@ array_ass_sub(PyArrayObject *self, PyObject *ind, PyObject *op)
/* Boolean indexing special case */
if (PyArray_Check(ind) &&
(PyArray_TYPE((PyArrayObject *)ind) == NPY_BOOL) &&
- (PyArray_NDIM(self) == PyArray_NDIM((PyArrayObject *)ind))) {
+ (PyArray_NDIM(self) == PyArray_NDIM((PyArrayObject *)ind)) &&
+ (PyArray_SIZE(self) == PyArray_SIZE((PyArrayObject *)ind))) {
int retcode;
PyArrayObject *op_arr;
PyArray_Descr *dtype = NULL;
View
35 numpy/core/tests/test_multiarray.py
@@ -1058,6 +1058,41 @@ def test_tuple(self):
x[:,:,(0,)] = 2.0
assert_array_equal(x, array([[[2.0]]]))
+ def test_mask(self):
+ x = array([1,2,3,4])
+ m = array([0,1],bool)
+ assert_array_equal(x[m], array([2]))
+
+ def test_mask2(self):
+ x = array([[1,2,3,4],[5,6,7,8]])
+ m = array([0,1],bool)
+ m2 = array([[0,1],[1,0]], bool)
+ m3 = array([[0,1]], bool)
+ assert_array_equal(x[m], array([[5,6,7,8]]))
+ assert_array_equal(x[m2], array([2,5]))
+ assert_array_equal(x[m3], array([2]))
+
+ def test_assign_mask(self):
+ x = array([1,2,3,4])
+ m = array([0,1],bool)
+ x[m] = 5
+ assert_array_equal(x, array([1,5,3,4]))
+
+ def test_assign_mask(self):
+ xorig = array([[1,2,3,4],[5,6,7,8]])
+ m = array([0,1],bool)
+ m2 = array([[0,1],[1,0]],bool)
+ m3 = array([[0,1]], bool)
+ x = xorig.copy()
+ x[m] = 10
+ assert_array_equal(x, array([[1,2,3,4],[10,10,10,10]]))
+ x = xorig.copy()
+ x[m2] = 10
+ assert_array_equal(x, array([[1,10,3,4],[10,6,7,8]]))
+ x = xorig.copy()
+ x[m3] = 10
+ assert_array_equal(x, array([[1,10,3,4],[5,6,7,8]]))
+
class TestStringCompare(TestCase):
def test_string(self):
Please sign in to comment.
Something went wrong with that request. Please try again.