Skip to content

Commit ec78371

Browse files
authored
Merge branch 'master' into impl-piecewise
2 parents 37b014f + 77a90bf commit ec78371

File tree

4 files changed

+27
-28
lines changed

4 files changed

+27
-28
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5151
* Avoided negating unsigned integers in ceil division used in `dpnp.resize` implementation [#2508](https://github.com/IntelPython/dpnp/pull/2508)
5252
* 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)
5353
* Resolved issue when `dpnp.ndarray` constructor is called with `dpnp.ndarray.data` as `buffer` keyword [#2533](https://github.com/IntelPython/dpnp/pull/2533)
54+
* Fixed `dpnp.linalg.cond` to always return a real dtype [#2547](https://github.com/IntelPython/dpnp/pull/2547)
5455

5556
### Security
5657

dpnp/linalg/dpnp_utils_linalg.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1976,13 +1976,15 @@ def dpnp_cond(x, p=None):
19761976
else:
19771977
r = s[..., 0] / s[..., -1]
19781978
else:
1979-
result_t = _common_type(x)
19801979
# The result array will contain nans in the entries
19811980
# where inversion failed
19821981
invx = dpnp.linalg.inv(x)
19831982
r = dpnp.linalg.norm(x, p, axis=(-2, -1)) * dpnp.linalg.norm(
19841983
invx, p, axis=(-2, -1)
19851984
)
1985+
1986+
# condition number is always real
1987+
result_t = _real_type(_common_type(x), device=x.sycl_queue)
19861988
r = r.astype(result_t, copy=False)
19871989

19881990
# Convert nans to infs unless the original array had nan entries

dpnp/tests/test_linalg.py

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -278,15 +278,12 @@ def test_cholesky_errors(self):
278278

279279

280280
class TestCond:
281-
def setup_method(self):
282-
numpy.random.seed(70)
281+
_norms = [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
283282

284283
@pytest.mark.parametrize(
285-
"shape", [(0, 4, 4), (4, 0, 3, 3)], ids=["(0, 5, 3)", "(4, 0, 2, 3)"]
286-
)
287-
@pytest.mark.parametrize(
288-
"p", [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
284+
"shape", [(0, 4, 4), (4, 0, 3, 3)], ids=["(0, 4, 4)", "(4, 0, 3, 3)"]
289285
)
286+
@pytest.mark.parametrize("p", _norms)
290287
def test_empty(self, shape, p):
291288
a = numpy.empty(shape)
292289
ia = dpnp.array(a)
@@ -295,26 +292,27 @@ def test_empty(self, shape, p):
295292
expected = numpy.linalg.cond(a, p=p)
296293
assert_dtype_allclose(result, expected)
297294

295+
# TODO: uncomment once numpy 2.3.3 release is published
296+
# @testing.with_requires("numpy>=2.3.3")
298297
@pytest.mark.parametrize(
299298
"dtype", get_all_dtypes(no_none=True, no_bool=True)
300299
)
301300
@pytest.mark.parametrize(
302301
"shape", [(4, 4), (2, 4, 3, 3)], ids=["(4, 4)", "(2, 4, 3, 3)"]
303302
)
304-
@pytest.mark.parametrize(
305-
"p", [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
306-
)
303+
@pytest.mark.parametrize("p", _norms)
307304
def test_basic(self, dtype, shape, p):
308305
a = generate_random_numpy_array(shape, dtype)
309306
ia = dpnp.array(a)
310307

311308
result = dpnp.linalg.cond(ia, p=p)
312309
expected = numpy.linalg.cond(a, p=p)
310+
# TODO: remove when numpy#29333 is released
311+
if numpy_version() < "2.3.3":
312+
expected = expected.real
313313
assert_dtype_allclose(result, expected, factor=16)
314314

315-
@pytest.mark.parametrize(
316-
"p", [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
317-
)
315+
@pytest.mark.parametrize("p", _norms)
318316
def test_bool(self, p):
319317
a = numpy.array([[True, True], [True, False]])
320318
ia = dpnp.array(a)
@@ -323,9 +321,7 @@ def test_bool(self, p):
323321
expected = numpy.linalg.cond(a, p=p)
324322
assert_dtype_allclose(result, expected)
325323

326-
@pytest.mark.parametrize(
327-
"p", [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
328-
)
324+
@pytest.mark.parametrize("p", _norms)
329325
def test_nan_to_inf(self, p):
330326
a = numpy.zeros((2, 2))
331327
ia = dpnp.array(a)
@@ -343,9 +339,7 @@ def test_nan_to_inf(self, p):
343339
else:
344340
assert_raises(dpnp.linalg.LinAlgError, dpnp.linalg.cond, ia, p=p)
345341

346-
@pytest.mark.parametrize(
347-
"p", [None, -dpnp.inf, -2, -1, 1, 2, dpnp.inf, "fro"]
348-
)
342+
@pytest.mark.parametrize("p", _norms)
349343
@pytest.mark.parametrize(
350344
"stride",
351345
[(-2, -3, 2, -2), (-2, 4, -4, -4), (2, 3, 4, 4), (-1, 3, 3, -3)],
@@ -357,21 +351,23 @@ def test_nan_to_inf(self, p):
357351
],
358352
)
359353
def test_strided(self, p, stride):
360-
A = numpy.random.rand(6, 8, 10, 10)
361-
B = dpnp.asarray(A)
354+
A = generate_random_numpy_array(
355+
(6, 8, 10, 10), seed_value=70, low=0, high=1
356+
)
357+
iA = dpnp.array(A)
362358
slices = tuple(slice(None, None, stride[i]) for i in range(A.ndim))
363-
a = A[slices]
364-
b = B[slices]
359+
a, ia = A[slices], iA[slices]
365360

366-
result = dpnp.linalg.cond(b, p=p)
361+
result = dpnp.linalg.cond(ia, p=p)
367362
expected = numpy.linalg.cond(a, p=p)
368363
assert_dtype_allclose(result, expected, factor=24)
369364

370-
def test_error(self):
365+
@pytest.mark.parametrize("xp", [dpnp, numpy])
366+
def test_error(self, xp):
371367
# cond is not defined on empty arrays
372-
ia = dpnp.empty((2, 0))
368+
a = xp.empty((2, 0))
373369
with pytest.raises(ValueError):
374-
dpnp.linalg.cond(ia, p=1)
370+
xp.linalg.cond(a, p=1)
375371

376372

377373
class TestDet:

environments/build_conda_pkg.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ channels:
33
- conda-forge
44
dependencies:
55
- python=3.13
6-
- conda-build=25.5.0
6+
- conda-build=25.7.0

0 commit comments

Comments
 (0)