From 33351f646e0b523139fbba4986eba54a3bfe55a7 Mon Sep 17 00:00:00 2001 From: Jim Date: Thu, 12 Mar 2020 19:05:22 +0100 Subject: MAINT: Add better error handling in linalg.norm for vectors and clarify it in documentation (#15740) * Clarify `fro` and `nuc` usage in linalg.norm documentation (see #15533). * Add improved error handling when getting Frobenius norm from a vector (see #15533). * Fix comment in linalg norm test. Closes gh-15533. --- numpy/linalg/linalg.py | 11 +++++++---- numpy/linalg/tests/test_linalg.py | 3 ++- numpy/linalg/tests/test_regression.py | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py index 85f714ebf..eb03932e1 100644 --- a/numpy/linalg/linalg.py +++ b/numpy/linalg/linalg.py @@ -2434,6 +2434,9 @@ def norm(x, ord=None, axis=None, keepdims=False): The nuclear norm is the sum of the singular values. + Both the Frobenius and nuclear norm orders are only defined for + matrices and raise a ValueError when ``x.ndim != 2``. + References ---------- .. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*, @@ -2556,11 +2559,11 @@ def norm(x, ord=None, axis=None, keepdims=False): # special case for speedup s = (x.conj() * x).real return sqrt(add.reduce(s, axis=axis, keepdims=keepdims)) + # None of the str-type keywords for ord ('fro', 'nuc') + # are valid for vectors + elif isinstance(ord, str): + raise ValueError(f"Invalid norm order '{ord}' for vectors") else: - try: - ord + 1 - except TypeError: - raise ValueError("Invalid norm order for vectors.") absx = abs(x) absx **= ord ret = add.reduce(absx, axis=axis, keepdims=keepdims) diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py index 04f5c3d19..dae4ef61e 100644 --- a/numpy/linalg/tests/test_linalg.py +++ b/numpy/linalg/tests/test_linalg.py @@ -1480,11 +1480,12 @@ class _TestNorm2D(_TestNormBase): # Using `axis=` or passing in a 1-D array implies vector # norms are being computed, so also using `ord='fro'` - # or `ord='nuc'` raises a ValueError. + # or `ord='nuc'` or any other string raises a ValueError. assert_raises(ValueError, norm, A, 'fro', 0) assert_raises(ValueError, norm, A, 'nuc', 0) assert_raises(ValueError, norm, [3, 4], 'fro', None) assert_raises(ValueError, norm, [3, 4], 'nuc', None) + assert_raises(ValueError, norm, [3, 4], 'test', None) # Similarly, norm should raise an exception when ord is any finite # number other than 1, 2, -1 or -2 when computing matrix norms. diff --git a/numpy/linalg/tests/test_regression.py b/numpy/linalg/tests/test_regression.py index 1ae207b49..7ed932bc9 100644 --- a/numpy/linalg/tests/test_regression.py +++ b/numpy/linalg/tests/test_regression.py @@ -57,8 +57,8 @@ class TestRegression: assert_array_almost_equal(b, np.zeros((2, 2))) def test_norm_vector_badarg(self): - # Regression for #786: Froebenius norm for vectors raises - # TypeError. + # Regression for #786: Frobenius norm for vectors raises + # ValueError. assert_raises(ValueError, linalg.norm, array([1., 2., 3.]), 'fro') def test_lapack_endian(self): -- cgit v1.2.1