Skip to content

Commit 7effabc

Browse files
Add implementation of dpnp.linalg.svdvals() (#2094)
* Add implementation of dpnp.linalg.svdvals * Add TestSvdvals to test_linalg.py * Add dpnp.linalg.svdvals to docs * Update doc/reference/linalg.rst --------- Co-authored-by: Anton <[email protected]>
1 parent c4677e9 commit 7effabc

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

doc/reference/linalg.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ Decompositions
3030
:nosignatures:
3131

3232
dpnp.linalg.cholesky
33+
dpnp.linalg.outer
3334
dpnp.linalg.qr
3435
dpnp.linalg.svd
36+
dpnp.linalg.svdvals
3537

3638
Matrix eigenvalues
3739
------------------

dpnp/linalg/dpnp_iface_linalg.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
"qr",
8484
"solve",
8585
"svd",
86+
"svdvals",
8687
"slogdet",
8788
"tensorinv",
8889
"tensorsolve",
@@ -1315,6 +1316,62 @@ def svd(a, full_matrices=True, compute_uv=True, hermitian=False):
13151316
return dpnp_svd(a, full_matrices, compute_uv, hermitian)
13161317

13171318

1319+
def svdvals(x, /):
1320+
"""
1321+
Returns the singular values of a matrix (or a stack of matrices) `x`.
1322+
1323+
When `x` is a stack of matrices, the function will compute
1324+
the singular values for each matrix in the stack.
1325+
1326+
Calling ``dpnp.linalg.svdvals(x)`` to get singular values is the same as
1327+
``dpnp.linalg.svd(x, compute_uv=False, hermitian=False)``.
1328+
1329+
For full documentation refer to :obj:`numpy.linalg.svdvals`.
1330+
1331+
Parameters
1332+
----------
1333+
x : (..., M, N) {dpnp.ndarray, usm_ndarray}
1334+
Input array with ``x.ndim >= 2`` and whose last two dimensions
1335+
form matrices on which to perform singular value decomposition.
1336+
1337+
Returns
1338+
-------
1339+
out : (..., K) dpnp.ndarray
1340+
Vector(s) of singular values of length K, where K = min(M, N).
1341+
1342+
1343+
See Also
1344+
--------
1345+
:obj:`dpnp.linalg.svd` : Compute the singular value decomposition.
1346+
1347+
1348+
Examples
1349+
--------
1350+
>>> import dpnp as np
1351+
>>> a = np.array([[3, 0], [0, 4]])
1352+
>>> np.linalg.svdvals(a)
1353+
array([4., 3.])
1354+
1355+
This is equivalent to calling:
1356+
1357+
>>> np.linalg.svd(a, compute_uv=False, hermitian=False)
1358+
array([4., 3.])
1359+
1360+
Stack of matrices:
1361+
1362+
>>> b = np.array([[[6, 0], [0, 8]], [[9, 0], [0, 12]]])
1363+
>>> np.linalg.svdvals(b)
1364+
array([[ 8., 6.],
1365+
[12., 9.]])
1366+
1367+
"""
1368+
1369+
dpnp.check_supported_arrays_type(x)
1370+
assert_stacked_2d(x)
1371+
1372+
return dpnp_svd(x, full_matrices=True, compute_uv=False, hermitian=False)
1373+
1374+
13181375
def slogdet(a):
13191376
"""
13201377
Compute the sign and (natural) logarithm of the determinant of an array.

tests/test_linalg.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2993,6 +2993,50 @@ def test_svd_errors(self):
29932993
assert_raises(inp.linalg.LinAlgError, inp.linalg.svd, a_dp_ndim_1)
29942994

29952995

2996+
# numpy.linalg.svdvals() is available since numpy >= 2.0
2997+
@testing.with_requires("numpy>=2.0")
2998+
class TestSvdvals:
2999+
@pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True))
3000+
@pytest.mark.parametrize(
3001+
"shape",
3002+
[(3, 5), (4, 2), (2, 3, 3), (3, 5, 2)],
3003+
ids=["(3,5)", "(4,2)", "(2,3,3)", "(3,5,2)"],
3004+
)
3005+
def test_svdvals(self, dtype, shape):
3006+
a = numpy.arange(numpy.prod(shape), dtype=dtype).reshape(shape)
3007+
dp_a = inp.array(a)
3008+
3009+
expected = numpy.linalg.svdvals(a)
3010+
result = inp.linalg.svdvals(dp_a)
3011+
3012+
assert_dtype_allclose(result, expected)
3013+
3014+
@pytest.mark.parametrize(
3015+
"shape",
3016+
[(0, 0), (1, 0, 0), (0, 2, 2)],
3017+
ids=["(0,0)", "(1,0,0)", "(0,2,2)"],
3018+
)
3019+
def test_svdvals_empty(self, shape):
3020+
a = generate_random_numpy_array(shape, inp.default_float_type())
3021+
dp_a = inp.array(a)
3022+
3023+
expected = numpy.linalg.svdvals(a)
3024+
result = inp.linalg.svdvals(dp_a)
3025+
3026+
assert_dtype_allclose(result, expected)
3027+
3028+
def test_svdvals_errors(self):
3029+
a_dp = inp.array([[1, 2], [3, 4]], dtype="float32")
3030+
3031+
# unsupported type
3032+
a_np = inp.asnumpy(a_dp)
3033+
assert_raises(TypeError, inp.linalg.svdvals, a_np)
3034+
3035+
# a.ndim < 2
3036+
a_dp_ndim_1 = a_dp.flatten()
3037+
assert_raises(inp.linalg.LinAlgError, inp.linalg.svdvals, a_dp_ndim_1)
3038+
3039+
29963040
class TestPinv:
29973041
def get_tol(self, dtype):
29983042
tol = 1e-06

0 commit comments

Comments
 (0)