diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/arraytypes.c.src | 2 | ||||
-rw-r--r-- | numpy/core/src/multiarray/mapping.c | 28 | ||||
-rw-r--r-- | numpy/core/tests/test_regression.py | 7 | ||||
-rw-r--r-- | numpy/doc/broadcasting.py | 9 | ||||
-rw-r--r-- | numpy/linalg/linalg.py | 15 | ||||
-rw-r--r-- | numpy/linalg/tests/test_linalg.py | 30 |
6 files changed, 62 insertions, 29 deletions
diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src index b4158ec8e..d622effe6 100644 --- a/numpy/core/src/multiarray/arraytypes.c.src +++ b/numpy/core/src/multiarray/arraytypes.c.src @@ -733,7 +733,7 @@ VOID_getitem(void *input, void *vap) return (PyObject *)ret; } - return PyBytes_FromStringAndSize(PyArray_DATA(ap), descr->elsize); + return PyBytes_FromStringAndSize(ip, descr->elsize); } diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index f338226c2..2fdb3ebf6 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -2915,20 +2915,20 @@ PyArray_MapIterNew(npy_index_info *indices , int index_num, int index_type, Py_INCREF(extra_op_dtype); mit->extra_op_dtype = extra_op_dtype; - /* Create an iterator, just to broadcast the arrays?! */ - tmp_iter = NpyIter_MultiNew(mit->numiter, index_arrays, - NPY_ITER_ZEROSIZE_OK | - NPY_ITER_REFS_OK | - NPY_ITER_MULTI_INDEX | - NPY_ITER_DONT_NEGATE_STRIDES, - NPY_KEEPORDER, - NPY_UNSAFE_CASTING, - tmp_op_flags, NULL); - if (tmp_iter == NULL) { - goto fail; - } - if (PyArray_SIZE(subspace) == 1) { + /* Create an iterator, just to broadcast the arrays?! */ + tmp_iter = NpyIter_MultiNew(mit->numiter, index_arrays, + NPY_ITER_ZEROSIZE_OK | + NPY_ITER_REFS_OK | + NPY_ITER_MULTI_INDEX | + NPY_ITER_DONT_NEGATE_STRIDES, + NPY_KEEPORDER, + NPY_UNSAFE_CASTING, + tmp_op_flags, NULL); + if (tmp_iter == NULL) { + goto fail; + } + /* * nditer allows itemsize with npy_intp type, so it works * here, but it would *not* work directly, since elsize @@ -2941,6 +2941,7 @@ PyArray_MapIterNew(npy_index_info *indices , int index_num, int index_type, "internal error: failed to find output array strides"); goto fail; } + NpyIter_Deallocate(tmp_iter); } else { /* Just use C-order strides (TODO: allow also F-order) */ @@ -2950,7 +2951,6 @@ PyArray_MapIterNew(npy_index_info *indices , int index_num, int index_type, stride *= mit->dimensions[i]; } } - NpyIter_Deallocate(tmp_iter); /* shape is set, and strides is set up to mit->nd, set rest */ PyArray_CreateSortedStridePerm(PyArray_NDIM(subspace), diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 5f4410d54..36478ddb7 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -2368,6 +2368,13 @@ class TestRegression(object): del va assert_equal(x, b'\x00\x00\x00\x00') + def test_void_getitem(self): + # Test fix for gh-11668. + assert_(np.array([b'a'], 'V1').astype('O') == b'a') + assert_(np.array([b'ab'], 'V2').astype('O') == b'ab') + assert_(np.array([b'abc'], 'V3').astype('O') == b'abc') + assert_(np.array([b'abcd'], 'V4').astype('O') == b'abcd') + def test_structarray_title(self): # The following used to segfault on pypy, due to NPY_TITLE_KEY # not working properly and resulting to double-decref of the diff --git a/numpy/doc/broadcasting.py b/numpy/doc/broadcasting.py index 1dc4f60bf..6c3a4bc75 100644 --- a/numpy/doc/broadcasting.py +++ b/numpy/doc/broadcasting.py @@ -53,9 +53,10 @@ dimensions are compatible when 2) one of them is 1 If these conditions are not met, a -``ValueError: frames are not aligned`` exception is thrown, indicating that -the arrays have incompatible shapes. The size of the resulting array -is the maximum size along each dimension of the input arrays. +``ValueError: operands could not be broadcast together`` exception is +thrown, indicating that the arrays have incompatible shapes. The size of +the resulting array is the maximum size along each dimension of the input +arrays. Arrays do not need to have the same *number* of dimensions. For example, if you have a ``256x256x3`` array of RGB values, and you want to scale @@ -124,7 +125,7 @@ An example of broadcasting in practice:: (5,) >>> x + y - <type 'exceptions.ValueError'>: shape mismatch: objects cannot be broadcast to a single shape + ValueError: operands could not be broadcast together with shapes (4,) (5,) >>> xx.shape (4, 1) diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py index c3b76ada7..5f04620ac 100644 --- a/numpy/linalg/linalg.py +++ b/numpy/linalg/linalg.py @@ -133,11 +133,6 @@ def _linalgRealType(t): """Cast the type t to either double or cdouble.""" return double -_complex_types_map = {single : csingle, - double : cdouble, - csingle : csingle, - cdouble : cdouble} - def _commonType(*arrays): # in lite version, use higher precision (always double or cdouble) result_type = single @@ -2115,7 +2110,6 @@ def lstsq(a, b, rcond="warn"): if is_1d: b = b[:, newaxis] _assertRank2(a, b) - _assertNoEmpty2d(a, b) # TODO: relax this constraint m, n = a.shape[-2:] m2, n_rhs = b.shape[-2:] if m != m2: @@ -2146,7 +2140,16 @@ def lstsq(a, b, rcond="warn"): signature = 'DDd->Ddid' if isComplexType(t) else 'ddd->ddid' extobj = get_linalg_error_extobj(_raise_linalgerror_lstsq) + if n_rhs == 0: + # lapack can't handle n_rhs = 0 - so allocate the array one larger in that axis + b = zeros(b.shape[:-2] + (m, n_rhs + 1), dtype=b.dtype) x, resids, rank, s = gufunc(a, b, rcond, signature=signature, extobj=extobj) + if m == 0: + x[...] = 0 + if n_rhs == 0: + # remove the item we added + x = x[..., :n_rhs] + resids = resids[..., :n_rhs] # remove the axis we added if is_1d: diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py index 0df673884..36b677ac3 100644 --- a/numpy/linalg/tests/test_linalg.py +++ b/numpy/linalg/tests/test_linalg.py @@ -875,14 +875,12 @@ class TestDet(DetCases): class LstsqCases(LinalgSquareTestCase, LinalgNonsquareTestCase): def do(self, a, b, tags): - if 'size-0' in tags: - assert_raises(LinAlgError, linalg.lstsq, a, b) - return - arr = np.asarray(a) m, n = arr.shape u, s, vt = linalg.svd(a, 0) x, residuals, rank, sv = linalg.lstsq(a, b, rcond=-1) + if m == 0: + assert_((x == 0).all()) if m <= n: assert_almost_equal(b, dot(a, x)) assert_equal(rank, m) @@ -923,6 +921,30 @@ class TestLstsq(LstsqCases): # Warning should be raised exactly once (first command) assert_(len(w) == 1) + @pytest.mark.parametrize(["m", "n", "n_rhs"], [ + (4, 2, 2), + (0, 4, 1), + (0, 4, 2), + (4, 0, 1), + (4, 0, 2), + (4, 2, 0), + (0, 0, 0) + ]) + def test_empty_a_b(self, m, n, n_rhs): + a = np.arange(m * n).reshape(m, n) + b = np.ones((m, n_rhs)) + x, residuals, rank, s = linalg.lstsq(a, b, rcond=None) + if m == 0: + assert_((x == 0).all()) + assert_equal(x.shape, (n, n_rhs)) + assert_equal(residuals.shape, ((n_rhs,) if m > n else (0,))) + if m > n and n_rhs > 0: + # residuals are exactly the squared norms of b's columns + r = b - np.dot(a, x) + assert_almost_equal(residuals, (r * r).sum(axis=-2)) + assert_equal(rank, min(m, n)) + assert_equal(s.shape, (min(m, n),)) + class TestMatrixPower(object): R90 = array([[0, 1], [-1, 0]]) |