Skip to content
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ This release achieves 100% compliance with Python Array API specification (revis
* Updated FFT module to ensure an input array is Hermitian before calling complex-to-real FFT [#2444](https://github.com/IntelPython/dpnp/pull/2444)
* Aligned `black` configuration with the list of supported python versions [#2457](https://github.com/IntelPython/dpnp/pull/2457)
* Use `pyproject.toml` instead of `setup.py` aligning with current packaging best practices [#2462](https://github.com/IntelPython/dpnp/pull/2462)
* Added a clarification to `dpnp.linalg.cond` docstring about its behavior with singular matrices [#2500] (https://github.com/IntelPython/dpnp/pull/2500)

### Fixed

Expand Down
8 changes: 8 additions & 0 deletions dpnp/linalg/dpnp_iface_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,14 @@ def cond(x, p=None):
--------
:obj:`dpnp.linalg.norm` : Matrix or vector norm.

Notes
-----
This function will raise :class:`dpnp.linalg.LinAlgError` on singular input
when using any of the norm: ``1``, ``-1``, ``inf``, ``-inf``, or ``'fro'``.
In contrast, :obj:`numpy.linalg.cond` will fill the result array with
``inf`` values for each 2D batch in the input array that is singular
when using these norms.

Examples
--------
>>> import dpnp as np
Expand Down
35 changes: 14 additions & 21 deletions dpnp/tests/test_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,29 +326,22 @@ def test_bool(self, p):
@pytest.mark.parametrize(
"p", [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
)
def test_nan(self, p):
# dpnp.linalg.cond uses dpnp.linalg.inv()
# for the case when p is not None or p != -2 or p != 2
# For singular matrices cuSolver raises an error
# while OneMKL returns nans
if is_cuda_device() and p in [-dpnp.inf, -1, 1, dpnp.inf, "fro"]:
pytest.skip("Different behavior on CUDA")
elif requires_intel_mkl_version("2025.2") and p in [
-dpnp.inf,
-1,
1,
dpnp.inf,
"fro",
]:
pytest.skip("SAT-7966")
a = generate_random_numpy_array((2, 2, 2, 2))
a[0, 0] = 0
a[1, 1] = 0
def test_nan_to_inf(self, p):
a = numpy.zeros((2, 2))
ia = dpnp.array(a)

result = dpnp.linalg.cond(ia, p=p)
expected = numpy.linalg.cond(a, p=p)
assert_dtype_allclose(result, expected)
# NumPy does not raise LinAlgError on singular matrices.
# It returns `inf`, `0`, or large/small finite values
# depending on the norm and the matrix content.
# DPNP raises LinAlgError for 1, -1, inf, -inf, and 'fro'
# due to use of gesv in the 2D case.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you planning to add a test for > 2D case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, numpy behavior with singular matrices varies depending on the norm value and the matrix content so it is better not to rely on it in tests. This test was added to cover case nan to inf conversion to improve code coverage

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is about testing only that the exception raised?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the next PR I am going to remove synchronization with host and device while converting nan to inf which will cause changes in this test so I will add test for ND there

# For [None, 2, -2], DPNP does not raise.
if p in [None, 2, -2]:
result = dpnp.linalg.cond(ia, p=p)
expected = numpy.linalg.cond(a, p=p)
assert_dtype_allclose(result, expected)
else:
assert_raises(dpnp.linalg.LinAlgError, dpnp.linalg.cond, ia, p=p)

@pytest.mark.parametrize(
"p", [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
Expand Down
Loading