Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Avoided negating unsigned integers in ceil division used in `dpnp.resize` implementation [#2508](https://github.com/IntelPython/dpnp/pull/2508)
* Fixed `dpnp.unique` with 1d input array and `axis=0`, `equal_nan=True` keywords passed where the produced result doesn't collapse the NaNs [#2530](https://github.com/IntelPython/dpnp/pull/2530)
* Resolved issue when `dpnp.ndarray` constructor is called with `dpnp.ndarray.data` as `buffer` keyword [#2533](https://github.com/IntelPython/dpnp/pull/2533)
* Fixed `dpnp.linalg.cond` to always return a real dtype [#2547](https://github.com/IntelPython/dpnp/pull/2547)

### Security

Expand Down
4 changes: 3 additions & 1 deletion dpnp/linalg/dpnp_utils_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -1976,13 +1976,15 @@ def dpnp_cond(x, p=None):
else:
r = s[..., 0] / s[..., -1]
else:
result_t = _common_type(x)
# The result array will contain nans in the entries
# where inversion failed
invx = dpnp.linalg.inv(x)
r = dpnp.linalg.norm(x, p, axis=(-2, -1)) * dpnp.linalg.norm(
invx, p, axis=(-2, -1)
)

# condition number is always real
result_t = _real_type(_common_type(x), device=x.sycl_queue)
r = r.astype(result_t, copy=False)

# Convert nans to infs unless the original array had nan entries
Expand Down
36 changes: 17 additions & 19 deletions dpnp/tests/test_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,15 +278,15 @@ def test_cholesky_errors(self):


class TestCond:
_norms = [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]

def setup_method(self):
numpy.random.seed(70)

@pytest.mark.parametrize(
"shape", [(0, 4, 4), (4, 0, 3, 3)], ids=["(0, 5, 3)", "(4, 0, 2, 3)"]
)
@pytest.mark.parametrize(
"p", [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
"shape", [(0, 4, 4), (4, 0, 3, 3)], ids=["(0, 4, 4)", "(4, 0, 3, 3)"]
)
@pytest.mark.parametrize("p", _norms)
def test_empty(self, shape, p):
a = numpy.empty(shape)
ia = dpnp.array(a)
Expand All @@ -295,26 +295,27 @@ def test_empty(self, shape, p):
expected = numpy.linalg.cond(a, p=p)
assert_dtype_allclose(result, expected)

# TODO: uncomment once numpy 2.3.3 release is published
# @testing.with_requires("numpy>=2.3.3")
@pytest.mark.parametrize(
"dtype", get_all_dtypes(no_none=True, no_bool=True)
)
@pytest.mark.parametrize(
"shape", [(4, 4), (2, 4, 3, 3)], ids=["(4, 4)", "(2, 4, 3, 3)"]
)
@pytest.mark.parametrize(
"p", [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
)
@pytest.mark.parametrize("p", _norms)
def test_basic(self, dtype, shape, p):
a = generate_random_numpy_array(shape, dtype)
ia = dpnp.array(a)

result = dpnp.linalg.cond(ia, p=p)
expected = numpy.linalg.cond(a, p=p)
# TODO: remove when numpy#29333 is released
if numpy_version() < "2.3.3":
expected = expected.real
assert_dtype_allclose(result, expected, factor=16)

@pytest.mark.parametrize(
"p", [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
)
@pytest.mark.parametrize("p", _norms)
def test_bool(self, p):
a = numpy.array([[True, True], [True, False]])
ia = dpnp.array(a)
Expand All @@ -323,9 +324,7 @@ def test_bool(self, p):
expected = numpy.linalg.cond(a, p=p)
assert_dtype_allclose(result, expected)

@pytest.mark.parametrize(
"p", [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
)
@pytest.mark.parametrize("p", _norms)
def test_nan_to_inf(self, p):
a = numpy.zeros((2, 2))
ia = dpnp.array(a)
Expand All @@ -343,9 +342,7 @@ def test_nan_to_inf(self, p):
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"]
)
@pytest.mark.parametrize("p", _norms)
@pytest.mark.parametrize(
"stride",
[(-2, -3, 2, -2), (-2, 4, -4, -4), (2, 3, 4, 4), (-1, 3, 3, -3)],
Expand All @@ -367,11 +364,12 @@ def test_strided(self, p, stride):
expected = numpy.linalg.cond(a, p=p)
assert_dtype_allclose(result, expected, factor=24)

def test_error(self):
@pytest.mark.parametrize("xp", [dpnp, numpy])
def test_error(self, xp):
# cond is not defined on empty arrays
ia = dpnp.empty((2, 0))
a = xp.empty((2, 0))
with pytest.raises(ValueError):
dpnp.linalg.cond(ia, p=1)
xp.linalg.cond(a, p=1)


class TestDet:
Expand Down
Loading