From 02e511a24f3a60714980c9c18a1f354afc49e061 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Tue, 8 Oct 2024 12:02:50 +0200 Subject: [PATCH 1/5] Add implementation of dpnp.linalg.svdvals --- dpnp/linalg/dpnp_iface_linalg.py | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/dpnp/linalg/dpnp_iface_linalg.py b/dpnp/linalg/dpnp_iface_linalg.py index 69cf31303140..6863901b01e5 100644 --- a/dpnp/linalg/dpnp_iface_linalg.py +++ b/dpnp/linalg/dpnp_iface_linalg.py @@ -83,6 +83,7 @@ "qr", "solve", "svd", + "svdvals", "slogdet", "tensorinv", "tensorsolve", @@ -1315,6 +1316,62 @@ def svd(a, full_matrices=True, compute_uv=True, hermitian=False): return dpnp_svd(a, full_matrices, compute_uv, hermitian) +def svdvals(x, /): + """ + Returns the singular values of a matrix (or a stack of matrices) ``x``. + + When ``x`` is a stack of matrices, the function will compute + the singular values for each matrix in the stack. + + Calling ``dpnp.linalg.svdvals(x)`` to get singular values is the same as + ``dpnp.linalg.svd(x, compute_uv=False, hermitian=False)``. + + For full documentation refer to :obj:`numpy.linalg.svdvals`. + + Parameters + ---------- + x : (..., M, N) {dpnp.ndarray, usm_ndarray} + Input array with ``x.ndim >= 2`` and whose last two dimensions + form matrices on which to perform singular value decomposition. + + Returns + ------- + out : (..., K) dpnp.ndarray + Vector(s) of singular values of length K, where K = min(M, N). + + + See Also + -------- + :obj:`dpnp.linalg.svd` : Compute the singular value decomposition. + + + Examples + -------- + >>> import dpnp as np + >>> a = np.array([[3, 0], [0, 4]]) + >>> np.linalg.svdvals(a) + array([4., 3.]) + + This is equivalent to calling: + + >>> np.linalg.svd(a, compute_uv=False, hermitian=False) + array([4., 3.]) + + Stack of matrices: + + >>> b = np.array([[[6, 0], [0, 8]], [[9, 0], [0, 12]]]) + >>> np.linalg.svdvals(b) + array([[ 8., 6.], + [12., 9.]]) + + """ + + dpnp.check_supported_arrays_type(x) + assert_stacked_2d(x) + + return dpnp_svd(x, full_matrices=True, compute_uv=False, hermitian=False) + + def slogdet(a): """ Compute the sign and (natural) logarithm of the determinant of an array. From dc1b8f24710698bd165616fc089e969b2e2ee257 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Tue, 8 Oct 2024 12:03:48 +0200 Subject: [PATCH 2/5] Add TestSvdvals to test_linalg.py --- tests/test_linalg.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/test_linalg.py b/tests/test_linalg.py index 5951f103b170..d10f610e51c7 100644 --- a/tests/test_linalg.py +++ b/tests/test_linalg.py @@ -2993,6 +2993,50 @@ def test_svd_errors(self): assert_raises(inp.linalg.LinAlgError, inp.linalg.svd, a_dp_ndim_1) +# numpy.linalg.svdvals() is available since numpy >= 2.0 +@testing.with_requires("numpy>=2.0") +class TestSvdvals: + @pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True)) + @pytest.mark.parametrize( + "shape", + [(3, 5), (4, 2), (2, 3, 3), (3, 5, 2)], + ids=["(3,5)", "(4,2)", "(2,3,3)", "(3,5,2)"], + ) + def test_svdvals(self, dtype, shape): + a = numpy.arange(numpy.prod(shape), dtype=dtype).reshape(shape) + dp_a = inp.array(a) + + expected = numpy.linalg.svdvals(a) + result = inp.linalg.svdvals(dp_a) + + assert_dtype_allclose(result, expected) + + @pytest.mark.parametrize( + "shape", + [(0, 0), (1, 0, 0), (0, 2, 2)], + ids=["(0,0)", "(1,0,0)", "(0,2,2)"], + ) + def test_svdvals_empty(self, shape): + a = generate_random_numpy_array(shape, inp.default_float_type()) + dp_a = inp.array(a) + + expected = numpy.linalg.svdvals(a) + result = inp.linalg.svdvals(dp_a) + + assert_dtype_allclose(result, expected) + + def test_svdvals_errors(self): + a_dp = inp.array([[1, 2], [3, 4]], dtype="float32") + + # unsupported type + a_np = inp.asnumpy(a_dp) + assert_raises(TypeError, inp.linalg.svdvals, a_np) + + # a.ndim < 2 + a_dp_ndim_1 = a_dp.flatten() + assert_raises(inp.linalg.LinAlgError, inp.linalg.svdvals, a_dp_ndim_1) + + class TestPinv: def get_tol(self, dtype): tol = 1e-06 From 41356ec75bc23a322ddd49f7487e8ae46223fa31 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Wed, 9 Oct 2024 11:29:06 +0200 Subject: [PATCH 3/5] Add dpnp.linalg.svdvals to docs --- doc/reference/linalg.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/reference/linalg.rst b/doc/reference/linalg.rst index ddde45cb41de..17372fadbd54 100644 --- a/doc/reference/linalg.rst +++ b/doc/reference/linalg.rst @@ -32,6 +32,7 @@ Decompositions dpnp.linalg.cholesky dpnp.linalg.qr dpnp.linalg.svd + dpnp.linalg.svdvals Matrix eigenvalues ------------------ From f9cbe7deffd6c519fb23477ac026b56316a53307 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Wed, 9 Oct 2024 11:31:14 +0200 Subject: [PATCH 4/5] Apply review remarks --- dpnp/linalg/dpnp_iface_linalg.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dpnp/linalg/dpnp_iface_linalg.py b/dpnp/linalg/dpnp_iface_linalg.py index 6863901b01e5..712e8c5ba666 100644 --- a/dpnp/linalg/dpnp_iface_linalg.py +++ b/dpnp/linalg/dpnp_iface_linalg.py @@ -1318,9 +1318,9 @@ def svd(a, full_matrices=True, compute_uv=True, hermitian=False): def svdvals(x, /): """ - Returns the singular values of a matrix (or a stack of matrices) ``x``. + Returns the singular values of a matrix (or a stack of matrices) `x`. - When ``x`` is a stack of matrices, the function will compute + When `x` is a stack of matrices, the function will compute the singular values for each matrix in the stack. Calling ``dpnp.linalg.svdvals(x)`` to get singular values is the same as From a153a7b09ad259c881f45678b3874da8687c6f1b Mon Sep 17 00:00:00 2001 From: Anton <100830759+antonwolfy@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:11:58 +0200 Subject: [PATCH 5/5] Update doc/reference/linalg.rst --- doc/reference/linalg.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/reference/linalg.rst b/doc/reference/linalg.rst index 17372fadbd54..0bb48a04cd9b 100644 --- a/doc/reference/linalg.rst +++ b/doc/reference/linalg.rst @@ -30,6 +30,7 @@ Decompositions :nosignatures: dpnp.linalg.cholesky + dpnp.linalg.outer dpnp.linalg.qr dpnp.linalg.svd dpnp.linalg.svdvals