Skip to content

Commit 74b3eff

Browse files
authored
Merge branch 'master' into onemath
2 parents 5e59b1f + 03e5ba0 commit 74b3eff

File tree

5 files changed

+159
-25
lines changed

5 files changed

+159
-25
lines changed

dpnp/linalg/dpnp_iface_linalg.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,22 @@ def cond(x, p=None):
180180
x : {dpnp.ndarray, usm_ndarray}
181181
The matrix whose condition number is sought.
182182
p : {None, 1, -1, 2, -2, inf, -inf, "fro"}, optional
183-
Order of the norm used in the condition number computation.
184-
``inf`` means the `dpnp.inf` object, and the Frobenius norm is
183+
Order of the norm used in the condition number computation:
184+
185+
===== ============================
186+
p norm for matrices
187+
===== ============================
188+
None 2-norm
189+
'fro' Frobenius norm
190+
inf max(sum(abs(x), axis=1))
191+
-inf min(sum(abs(x), axis=1))
192+
1 max(sum(abs(x), axis=0))
193+
-1 min(sum(abs(x), axis=0))
194+
2 2-norm (largest singular value)
195+
-2 smallest singular value
196+
===== ============================
197+
198+
``inf`` means the :obj:`dpnp.inf` object, and the Frobenius norm is
185199
the root-of-sum-of-squares norm.
186200
187201
Default: ``None``.

dpnp/tests/third_party/cupy/core_tests/test_internal.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ def test_two(self):
3838

3939
class TestGetSize:
4040

41-
def test_none(self):
42-
with testing.assert_warns(DeprecationWarning):
43-
assert internal.get_size(None) == ()
44-
4541
def check_collection(self, a):
4642
assert internal.get_size(a) == tuple(a)
4743

dpnp/tests/third_party/cupy/core_tests/test_ndarray.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,10 @@ def wrap_take(array, *args, **kwargs):
2525

2626

2727
class TestNdarrayInit(unittest.TestCase):
28-
@pytest.mark.skip("passing 'None' into shape arguments is not supported")
28+
2929
def test_shape_none(self):
30-
with testing.assert_warns(DeprecationWarning):
31-
a = cupy.ndarray(None)
32-
assert a.shape == ()
30+
with pytest.raises(TypeError):
31+
cupy.ndarray(None)
3332

3433
def test_shape_int(self):
3534
a = cupy.ndarray(3)

dpnp/tests/third_party/cupy/creation_tests/test_basic.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,13 @@ def test_empty_scalar(self, xp, dtype, order):
4747
a.fill(0)
4848
return a
4949

50-
@pytest.mark.skip("passing 'None' into shape arguments is not supported")
51-
@testing.with_requires("numpy>=1.20")
50+
@testing.with_requires("numpy>=2.3")
5251
@testing.for_CF_orders()
5352
@testing.for_all_dtypes()
54-
@testing.numpy_cupy_array_equal()
55-
def test_empty_scalar_none(self, xp, dtype, order):
56-
with testing.assert_warns(DeprecationWarning):
57-
a = xp.empty(None, dtype=dtype, order=order)
58-
a.fill(0)
59-
return a
53+
def test_empty_scalar_none(self, dtype, order):
54+
for xp in (numpy, cupy):
55+
with pytest.raises(TypeError):
56+
xp.empty(None, dtype=dtype, order=order)
6057

6158
@testing.for_CF_orders()
6259
@testing.for_all_dtypes()
@@ -206,14 +203,13 @@ def test_zeros(self, xp, dtype, order):
206203
def test_zeros_scalar(self, xp, dtype, order):
207204
return xp.zeros((), dtype=dtype, order=order)
208205

209-
@pytest.mark.skip("passing 'None' into shape arguments is not supported")
210-
@testing.with_requires("numpy>=1.20")
206+
@testing.with_requires("numpy>=2.3")
211207
@testing.for_CF_orders()
212208
@testing.for_all_dtypes()
213-
@testing.numpy_cupy_array_equal()
214-
def test_zeros_scalar_none(self, xp, dtype, order):
215-
with testing.assert_warns(DeprecationWarning):
216-
return xp.zeros(None, dtype=dtype, order=order)
209+
def test_zeros_scalar_none(self, dtype, order):
210+
for xp in (numpy, cupy):
211+
with pytest.raises(TypeError):
212+
xp.zeros(None, dtype=dtype, order=order)
217213

218214
@testing.for_CF_orders()
219215
@testing.for_all_dtypes()

dpnp/tests/third_party/cupy/linalg_tests/test_norms.py

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import pytest
55

66
import dpnp as cupy
7-
from dpnp.tests.helper import is_cpu_device
87
from dpnp.tests.third_party.cupy import testing
98

109

@@ -224,3 +223,133 @@ def test_slogdet_one_dim(self, dtype):
224223
a = testing.shaped_arange((2,), xp, dtype)
225224
with pytest.raises(xp.linalg.LinAlgError):
226225
xp.linalg.slogdet(a)
226+
227+
228+
@testing.parameterize(
229+
*testing.product({"ord": [-numpy.inf, -2, -1, 1, 2, numpy.inf, "fro"]})
230+
)
231+
class TestCond(unittest.TestCase):
232+
@testing.for_float_dtypes(no_float16=True)
233+
@testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-4)
234+
def test_singular_zeros(self, xp, dtype):
235+
if self.ord not in [None, 2, -2]:
236+
pytest.skip("no LinAlgError is raising on singular matrices")
237+
238+
A = xp.zeros(shape=(2, 2), dtype=dtype)
239+
result = xp.linalg.cond(A, self.ord)
240+
241+
# singular matrices don't always hit infinity.
242+
result = xp.asarray(result) # numpy is scalar and can't be replaced
243+
large_number = 1.0 / (xp.finfo(dtype).eps)
244+
result[result >= large_number] = xp.inf
245+
246+
return result
247+
248+
@testing.for_float_dtypes(no_float16=True)
249+
@testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-4)
250+
def test_singular_ones(self, xp, dtype):
251+
if self.ord not in [None, 2, -2]:
252+
pytest.skip("no LinAlgError is raising on singular matrices")
253+
254+
A = xp.ones(shape=(2, 2), dtype=dtype)
255+
result = xp.linalg.cond(A, self.ord)
256+
257+
# singular matrices don't always hit infinity.
258+
result = xp.asarray(result) # numpy is scalar and can't be replaced
259+
large_number = 1.0 / (xp.finfo(dtype).eps)
260+
result[result >= large_number] = xp.inf
261+
262+
return result
263+
264+
@testing.for_float_dtypes(no_float16=True)
265+
@testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-4)
266+
def test_stacked_singular(self, xp, dtype):
267+
if self.ord not in [None, 2, -2]:
268+
pytest.skip("no LinAlgError is raising on singular matrices")
269+
270+
# Check behavior when only some of the stacked matrices are
271+
# singular
272+
273+
A = xp.arange(16, dtype=dtype).reshape((2, 2, 2, 2))
274+
A[0, 0] = 0
275+
A[1, 1] = 0
276+
277+
res = xp.linalg.cond(A, self.ord)
278+
return res
279+
280+
@testing.for_float_dtypes(no_float16=True)
281+
@testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-4)
282+
def test_default(self, xp, dtype):
283+
A = testing.shaped_arange((2, 2), xp, dtype=dtype)
284+
return xp.linalg.cond(A)
285+
286+
@testing.for_float_dtypes(no_float16=True)
287+
@testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-4)
288+
def test_basic(self, xp, dtype):
289+
A = testing.shaped_arange((2, 2), xp, dtype=dtype)
290+
return xp.linalg.cond(A, self.ord)
291+
292+
@testing.for_float_dtypes(no_float16=True)
293+
@testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-4)
294+
def test_generalized_1(self, xp, dtype):
295+
A = testing.shaped_arange((2, 2), xp, dtype=dtype)
296+
A = xp.array([A, 2 * A, 3 * A])
297+
return xp.linalg.cond(A, self.ord)
298+
299+
@testing.for_float_dtypes(no_float16=True)
300+
@testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-4)
301+
def test_generalized_2(self, xp, dtype):
302+
A = testing.shaped_arange((2, 2), xp, dtype=dtype)
303+
A = xp.array([A, 2 * A, 3 * A])
304+
A = xp.array([A] * 2 * 3).reshape((3, 2) + A.shape)
305+
306+
return xp.linalg.cond(A, self.ord)
307+
308+
@testing.for_float_dtypes(no_float16=True)
309+
def test_0x0(self, dtype):
310+
for xp in (numpy, cupy):
311+
A = xp.empty((0, 0), dtype=dtype)
312+
with pytest.raises(
313+
xp.linalg.LinAlgError,
314+
match="cond is not defined on empty arrays",
315+
):
316+
xp.linalg.cond(A, self.ord)
317+
318+
@testing.for_float_dtypes(no_float16=True)
319+
@testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-4)
320+
def test_1x1(self, xp, dtype):
321+
A = xp.ones((1, 1), dtype=dtype)
322+
return xp.linalg.cond(A, self.ord)
323+
324+
@testing.for_float_dtypes(no_float16=True)
325+
@testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-4)
326+
def test_8x8(self, xp, dtype):
327+
A = testing.shaped_arange((8, 8), xp, dtype=dtype) + xp.diag(
328+
xp.ones(8, dtype=dtype)
329+
)
330+
return xp.linalg.cond(A, self.ord)
331+
332+
@pytest.mark.skip("only ndarray input is supported")
333+
@testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-4)
334+
def test_nonarray(self, xp):
335+
A = [[1.0, 2.0], [3.0, 4.0]]
336+
return xp.linalg.cond(A, self.ord)
337+
338+
@testing.for_float_dtypes(no_float16=True)
339+
@testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-4)
340+
def test_hermitian(self, xp, dtype):
341+
A = xp.array([[1.0, 2.0], [2.0, 1.0]], dtype=dtype)
342+
return xp.linalg.cond(A, self.ord)
343+
344+
345+
class TestCondBasicNonSVD(unittest.TestCase):
346+
def test_basic_nonsvd(self):
347+
# Smoketest the non-svd norms
348+
A = cupy.array([[1.0, 0, 1], [0, -2.0, 0], [0, 0, 3.0]])
349+
testing.assert_array_almost_equal(cupy.linalg.cond(A, cupy.inf), 4)
350+
testing.assert_array_almost_equal(cupy.linalg.cond(A, -cupy.inf), 2 / 3)
351+
testing.assert_array_almost_equal(cupy.linalg.cond(A, 1), 4)
352+
testing.assert_array_almost_equal(cupy.linalg.cond(A, -1), 0.5)
353+
testing.assert_array_almost_equal(
354+
cupy.linalg.cond(A, "fro"), numpy.sqrt(265 / 12)
355+
)

0 commit comments

Comments
 (0)