summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/release/1.16.0-notes.rst6
-rw-r--r--numpy/linalg/linalg.py14
-rw-r--r--numpy/linalg/tests/test_linalg.py31
3 files changed, 32 insertions, 19 deletions
diff --git a/doc/release/1.16.0-notes.rst b/doc/release/1.16.0-notes.rst
index b55d2d3f2..4d9a8782e 100644
--- a/doc/release/1.16.0-notes.rst
+++ b/doc/release/1.16.0-notes.rst
@@ -47,6 +47,12 @@ Even when no elements needed to be drawn, ``np.random.randint`` and
distribution. This has been fixed so that e.g.
``np.random.choice([], 0) == np.array([], dtype=float64)``.
+``linalg.qr`` now works with empty matrices
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Previously, a ``LinAlgError`` would be raised when empty matrix
+(with zero rows and/or columns) is passed in. This has been fixed
+so that outputs of appropriate shapes are returned for the various modes.
+
ARM support updated
-------------------
Support for ARM CPUs has been updated to accommodate 32 and 64 bit targets,
diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py
index f3a3b37a3..c3b76ada7 100644
--- a/numpy/linalg/linalg.py
+++ b/numpy/linalg/linalg.py
@@ -858,13 +858,13 @@ def qr(a, mode='reduced'):
a, wrap = _makearray(a)
_assertRank2(a)
- _assertNoEmpty2d(a)
m, n = a.shape
t, result_t = _commonType(a)
a = _fastCopyAndTranspose(t, a)
a = _to_native_byte_order(a)
mn = min(m, n)
tau = zeros((mn,), t)
+
if isComplexType(t):
lapack_routine = lapack_lite.zgeqrf
routine_name = 'zgeqrf'
@@ -875,14 +875,14 @@ def qr(a, mode='reduced'):
# calculate optimal size of work data 'work'
lwork = 1
work = zeros((lwork,), t)
- results = lapack_routine(m, n, a, m, tau, work, -1, 0)
+ results = lapack_routine(m, n, a, max(1, m), tau, work, -1, 0)
if results['info'] != 0:
raise LinAlgError('%s returns %d' % (routine_name, results['info']))
# do qr decomposition
- lwork = int(abs(work[0]))
+ lwork = max(1, n, int(abs(work[0])))
work = zeros((lwork,), t)
- results = lapack_routine(m, n, a, m, tau, work, lwork, 0)
+ results = lapack_routine(m, n, a, max(1, m), tau, work, lwork, 0)
if results['info'] != 0:
raise LinAlgError('%s returns %d' % (routine_name, results['info']))
@@ -918,14 +918,14 @@ def qr(a, mode='reduced'):
# determine optimal lwork
lwork = 1
work = zeros((lwork,), t)
- results = lapack_routine(m, mc, mn, q, m, tau, work, -1, 0)
+ results = lapack_routine(m, mc, mn, q, max(1, m), tau, work, -1, 0)
if results['info'] != 0:
raise LinAlgError('%s returns %d' % (routine_name, results['info']))
# compute q
- lwork = int(abs(work[0]))
+ lwork = max(1, n, int(abs(work[0])))
work = zeros((lwork,), t)
- results = lapack_routine(m, mc, mn, q, m, tau, work, lwork, 0)
+ results = lapack_routine(m, mc, mn, q, max(1, m), tau, work, lwork, 0)
if results['info'] != 0:
raise LinAlgError('%s returns %d' % (routine_name, results['info']))
diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py
index 1c24f1e04..0df673884 100644
--- a/numpy/linalg/tests/test_linalg.py
+++ b/numpy/linalg/tests/test_linalg.py
@@ -1582,9 +1582,25 @@ class TestQR(object):
assert_(isinstance(r2, a_type))
assert_almost_equal(r2, r1)
- def test_qr_empty(self):
- a = np.zeros((0, 2))
- assert_raises(linalg.LinAlgError, linalg.qr, a)
+
+ @pytest.mark.parametrize(["m", "n"], [
+ (3, 0),
+ (0, 3),
+ (0, 0)
+ ])
+ def test_qr_empty(self, m, n):
+ k = min(m, n)
+ a = np.empty((m, n))
+ a_type = type(a)
+ a_dtype = a.dtype
+
+ self.check_qr(a)
+
+ h, tau = np.linalg.qr(a, mode='raw')
+ assert_equal(h.dtype, np.double)
+ assert_equal(tau.dtype, np.double)
+ assert_equal(h.shape, (n, m))
+ assert_equal(tau.shape, (k,))
def test_mode_raw(self):
# The factorization is not unique and varies between libraries,
@@ -1625,15 +1641,6 @@ class TestQR(object):
self.check_qr(m2)
self.check_qr(m2.T)
- def test_0_size(self):
- # There may be good ways to do (some of this) reasonably:
- a = np.zeros((0, 0))
- assert_raises(linalg.LinAlgError, linalg.qr, a)
- a = np.zeros((0, 1))
- assert_raises(linalg.LinAlgError, linalg.qr, a)
- a = np.zeros((1, 0))
- assert_raises(linalg.LinAlgError, linalg.qr, a)
-
class TestCholesky(object):
# TODO: are there no other tests for cholesky?