diff options
Diffstat (limited to 'numpy')
| -rw-r--r-- | numpy/core/function_base.py | 5 | ||||
| -rw-r--r-- | numpy/core/src/multiarray/mapping.c | 28 | ||||
| -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 |
5 files changed, 58 insertions, 29 deletions
diff --git a/numpy/core/function_base.py b/numpy/core/function_base.py index fb72bada5..799b1418d 100644 --- a/numpy/core/function_base.py +++ b/numpy/core/function_base.py @@ -71,7 +71,10 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None): -------- arange : Similar to `linspace`, but uses a step size (instead of the number of samples). - logspace : Samples uniformly distributed in log space. + geomspace : Similar to `linspace`, but with numbers spaced evenly on a log + scale (a geometric progression). + logspace : Similar to `geomspace`, but with the end points specified as + logarithms. Examples -------- 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/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 ac3183e16..ccc437663 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 @@ -2127,7 +2122,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: @@ -2158,7 +2152,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 30db5f2fe..ce4a37b09 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),)) + @pytest.mark.parametrize('dt', [np.dtype(c) for c in '?bBhHiIqQefdgFDGO']) class TestMatrixPower(object): |
