From e513c69b9d5dee6208ede7262e09bd5635cc7029 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Mon, 26 Aug 2024 17:21:22 -0500 Subject: [PATCH 1/4] implement dpnp.ndim --- .github/workflows/conda-package.yml | 1 + dpnp/dpnp_array.py | 33 +++++++++- dpnp/dpnp_iface_manipulation.py | 53 +++++++++++++-- .../third_party/cupy/testing_test/__init__.py | 0 .../cupy/testing_test/test_ndim.py | 66 +++++++++++++++++++ 5 files changed, 147 insertions(+), 6 deletions(-) create mode 100644 tests/third_party/cupy/testing_test/__init__.py create mode 100644 tests/third_party/cupy/testing_test/test_ndim.py diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 9b97dba3fd6..2f9f7945488 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -62,6 +62,7 @@ env: third_party/cupy/sorting_tests third_party/cupy/statistics_tests/test_histogram.py third_party/cupy/statistics_tests/test_meanvar.py + third_party/cupy/testing_tests VER_JSON_NAME: 'version.json' VER_SCRIPT1: "import json; f = open('version.json', 'r'); j = json.load(f); f.close(); " VER_SCRIPT2: "d = j['dpnp'][0]; print('='.join((d[s] for s in ('version', 'build'))))" diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index 9f92b7e22c6..5eda6dd52ca 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -1115,7 +1115,38 @@ def nbytes(self): @property def ndim(self): - """Number of array dimensions.""" + """ + Return the number of dimensions of an array. + + For full documentation refer to :obj:`numpy.ndarray.ndim`. + + Parameters + ---------- + a : {dpnp.ndarray, usm_ndarray} + Input array. + + Returns + ------- + number_of_dimensions : int + The number of dimensions in `a`. + + See Also + -------- + :obj:`dpnp.ndim` : equivalent method for any array-like input. + :obj:`dpnp.shape` : Return the shape of an array. + :obj:`dpnp.ndarray.shape` : Return the shape of an array. + + Examples + -------- + >>> import dpnp as np + >>> x = np.array([1, 2, 3]) + >>> x.ndim + 1 + >>> y = np.zeros((2, 3, 4)) + >>> y.ndim + 3 + + """ return self._array_obj.ndim diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index 2f2b2c7f23a..6e09ee1fa40 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -66,6 +66,7 @@ "flipud", "hstack", "moveaxis", + "ndim", "ravel", "repeat", "reshape", @@ -1356,6 +1357,48 @@ def moveaxis(a, source, destination): ) +def ndim(a): + """ + Return the number of dimensions of array-like input. + + For full documentation refer to :obj:`numpy.ndim`. + + Parameters + ---------- + a : array_like + Input array. + + Returns + ------- + number_of_dimensions : int + The number of dimensions in `a`. Scalars are zero-dimensional. + + See Also + -------- + :obj:`dpnp.ndarray.ndim` : equivalent method for `dpnp.ndarray` + or `usm_ndarray` input. + :obj:`dpnp.shape` : Return the shape of an array. + :obj:`dpnp.ndarray.shape` : Return the shape of an array. + + Examples + -------- + >>> import dpnp as np + >>> a = [[1, 2, 3], [4, 5, 6]] + >>> np.ndim(a) + 2 + >>> a = np.asarray(a) + >>> np.ndim(a) + 2 + >>> np.ndim(1) + 0 + + """ + + if dpnp.is_supported_array_type(a): + return a.ndim + return numpy.ndim(a) + + def ravel(a, order="C"): """ Return a contiguous flattened array. @@ -1738,14 +1781,14 @@ def shape(a): Examples -------- - >>> import dpnp as dp - >>> dp.shape(dp.eye(3)) + >>> import dpnp as np + >>> np.shape(np.eye(3)) (3, 3) - >>> dp.shape([[1, 3]]) + >>> np.shape([[1, 3]]) (1, 2) - >>> dp.shape([0]) + >>> np.shape([0]) (1,) - >>> dp.shape(0) + >>> np.shape(0) () """ diff --git a/tests/third_party/cupy/testing_test/__init__.py b/tests/third_party/cupy/testing_test/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/third_party/cupy/testing_test/test_ndim.py b/tests/third_party/cupy/testing_test/test_ndim.py new file mode 100644 index 00000000000..0323ebb9794 --- /dev/null +++ b/tests/third_party/cupy/testing_test/test_ndim.py @@ -0,0 +1,66 @@ +import unittest + +import numpy + +import dpnp as cupy +from tests.third_party.cupy import testing + + +class TestNdim(unittest.TestCase): + @testing.numpy_cupy_equal() + def test_ndim_ndarray1d(self, xp): + return xp.ndim(xp.arange(5)) + + @testing.numpy_cupy_equal() + def test_ndim_ndarray2d(self, xp): + return xp.ndim(xp.ones((2, 4))) + + @testing.numpy_cupy_equal() + def test_ndim_ndarray0d(self, xp): + return xp.ndim(xp.asarray(5)) + + @testing.numpy_cupy_equal() + def test_ndim_scalar(self, xp): + return xp.ndim(5) + + @testing.numpy_cupy_equal() + def test_ndim_none(self, xp): + return xp.ndim(None) + + @testing.numpy_cupy_equal() + def test_ndim_string(self, xp): + return xp.ndim("abc") + + @testing.numpy_cupy_equal() + def test_ndim_list1(self, xp): + return xp.ndim([1, 2, 3]) + + @testing.numpy_cupy_equal() + def test_ndim_list2(self, xp): + return xp.ndim([[1, 2, 3], [4, 5, 6]]) + + @testing.numpy_cupy_equal() + def test_ndim_tuple(self, xp): + return xp.ndim(((1, 2, 3), (4, 5, 6))) + + @testing.numpy_cupy_equal() + def test_ndim_set(self, xp): + return xp.ndim({1, 2, 3}) + + @testing.numpy_cupy_equal() + def test_ndim_object(self, xp): + return xp.ndim(dict(a=5, b="b")) + + # numpy.dim works on dpnp arrays and dpnp.ndim works on NumPy arrays + def test_ndim_array_function(self): + a = cupy.ones((4, 4)) + assert numpy.ndim(a) == 2 + + a = cupy.asarray(5) + assert numpy.ndim(a) == 0 + + a = numpy.ones((4, 4)) + assert cupy.ndim(a) == 2 + + a = numpy.asarray(5) + assert cupy.ndim(a) == 0 From be21a032ee74ffb59eb472ab45e8c636729117c2 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Mon, 26 Aug 2024 18:53:25 -0500 Subject: [PATCH 2/4] rename direcotry --- .../third_party/cupy/{testing_test => testing_tests}/__init__.py | 0 .../third_party/cupy/{testing_test => testing_tests}/test_ndim.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/third_party/cupy/{testing_test => testing_tests}/__init__.py (100%) rename tests/third_party/cupy/{testing_test => testing_tests}/test_ndim.py (100%) diff --git a/tests/third_party/cupy/testing_test/__init__.py b/tests/third_party/cupy/testing_tests/__init__.py similarity index 100% rename from tests/third_party/cupy/testing_test/__init__.py rename to tests/third_party/cupy/testing_tests/__init__.py diff --git a/tests/third_party/cupy/testing_test/test_ndim.py b/tests/third_party/cupy/testing_tests/test_ndim.py similarity index 100% rename from tests/third_party/cupy/testing_test/test_ndim.py rename to tests/third_party/cupy/testing_tests/test_ndim.py From d6351118d2c89979cb2fa41ddb9393d7b0b64040 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Mon, 26 Aug 2024 22:52:44 -0500 Subject: [PATCH 3/4] implement dpnp.size --- .github/workflows/conda-package.yml | 2 +- dpnp/dpnp_array.py | 31 +++++++++- dpnp/dpnp_iface_manipulation.py | 58 ++++++++++++++++++- tests/test_manipulation.py | 24 ++++++++ .../cupy/{testing_tests => }/test_ndim.py | 0 .../cupy/testing_tests/__init__.py | 0 6 files changed, 110 insertions(+), 5 deletions(-) rename tests/third_party/cupy/{testing_tests => }/test_ndim.py (100%) delete mode 100644 tests/third_party/cupy/testing_tests/__init__.py diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 2f9f7945488..ef7078f4549 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -62,7 +62,7 @@ env: third_party/cupy/sorting_tests third_party/cupy/statistics_tests/test_histogram.py third_party/cupy/statistics_tests/test_meanvar.py - third_party/cupy/testing_tests + third_party/cupy/test_ndim.py VER_JSON_NAME: 'version.json' VER_SCRIPT1: "import json; f = open('version.json', 'r'); j = json.load(f); f.close(); " VER_SCRIPT2: "d = j['dpnp'][0]; print('='.join((d[s] for s in ('version', 'build'))))" diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index 5eda6dd52ca..1b4c8c3e172 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -1132,7 +1132,7 @@ def ndim(self): See Also -------- - :obj:`dpnp.ndim` : equivalent method for any array-like input. + :obj:`dpnp.ndim` : Equivalent method for any array-like input. :obj:`dpnp.shape` : Return the shape of an array. :obj:`dpnp.ndarray.shape` : Return the shape of an array. @@ -1420,7 +1420,34 @@ def shape(self, newshape): @property def size(self): - """Number of elements in the array.""" + """ + Number of elements in the array. + + Parameters + ---------- + a : {dpnp.ndarray, usm_ndarray} + Input array. + + Returns + ------- + element_count : int + Number of elements in the array. + + See Also + -------- + :obj:`dpnp.size` : Return the number of elements along a given axis. + :obj:`dpnp.shape` : Return the shape of an array. + :obj:`dpnp.ndarray.shape` : Return the shape of an array. + + Examples + -------- + >>> import dpnp as np + >>> x = np.zeros((3, 5, 2), dtype=np.complex64) + >>> x.size + 30 + + """ + return self._array_obj.size def sort(self, axis=-1, kind=None, order=None): diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index 6e09ee1fa40..852985ec67e 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -75,6 +75,7 @@ "rollaxis", "row_stack", "shape", + "size", "squeeze", "stack", "swapaxes", @@ -1366,7 +1367,7 @@ def ndim(a): Parameters ---------- a : array_like - Input array. + Input data. Returns ------- @@ -1375,7 +1376,7 @@ def ndim(a): See Also -------- - :obj:`dpnp.ndarray.ndim` : equivalent method for `dpnp.ndarray` + :obj:`dpnp.ndarray.ndim` : Equivalent method for `dpnp.ndarray` or `usm_ndarray` input. :obj:`dpnp.shape` : Return the shape of an array. :obj:`dpnp.ndarray.shape` : Return the shape of an array. @@ -1798,6 +1799,59 @@ def shape(a): return numpy.shape(a) +def size(a, axis=None): + """ + Return the number of elements along a given axis. + + For full documentation refer to :obj:`numpy.size`. + + Parameters + ---------- + a : array_like + Input data. + axis : {None, int}, optional + Axis along which the elements are counted. + By default, give the total number of elements. + Default: ``None``. + + Returns + ------- + element_count : int + Number of elements along the specified axis. + + See Also + -------- + :obj:`dpnp.ndarray.size` : number of elements in array. + :obj:`dpnp.shape` : Return the shape of an array. + :obj:`dpnp.ndarray.shape` : Return the shape of an array. + + Examples + -------- + >>> import dpnp as np + >>> a = [[1, 2, 3], [4, 5, 6]] + >>> np.size(a) + 6 + >>> np.size(a, 1) + 3 + >>> np.size(a, 0) + 2 + + >>> a = np.asarray(a) + >>> np.size(a) + 6 + >>> np.size(a, 1) + 3 + + """ + + if dpnp.is_supported_array_type(a): + if axis is None: + return a.size + return a.shape[axis] + + return numpy.size(a, axis) + + def squeeze(a, /, axis=None): """ Removes singleton dimensions (axes) from array `a`. diff --git a/tests/test_manipulation.py b/tests/test_manipulation.py index 79432af4b17..76b1e786539 100644 --- a/tests/test_manipulation.py +++ b/tests/test_manipulation.py @@ -89,6 +89,30 @@ def test_result_type_only_arrays(): assert dpnp.result_type(*X) == numpy.result_type(*X_np) +def test_ndim(): + a = [[1, 2, 3], [4, 5, 6]] + ia = dpnp.array(a) + + exp = numpy.ndim(a) + assert ia.ndim == exp + assert dpnp.ndim(a) == exp + assert dpnp.ndim(ia) == exp + + +def test_size(): + a = [[1, 2, 3], [4, 5, 6]] + ia = dpnp.array(a) + + exp = numpy.size(a) + assert ia.size == exp + assert dpnp.size(a) == exp + assert dpnp.size(ia) == exp + + exp = numpy.size(a, 0) + assert dpnp.size(a, 0) == exp + assert dpnp.size(ia, 0) == exp + + class TestRepeat: @pytest.mark.parametrize( "data", diff --git a/tests/third_party/cupy/testing_tests/test_ndim.py b/tests/third_party/cupy/test_ndim.py similarity index 100% rename from tests/third_party/cupy/testing_tests/test_ndim.py rename to tests/third_party/cupy/test_ndim.py diff --git a/tests/third_party/cupy/testing_tests/__init__.py b/tests/third_party/cupy/testing_tests/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 From 63453392dd934f68408bb0bbe405a4c2be539fe3 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Tue, 27 Aug 2024 12:40:20 -0500 Subject: [PATCH 4/4] remove parameters section --- dpnp/dpnp_array.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index 1b4c8c3e172..92f8b129f8e 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -1120,11 +1120,6 @@ def ndim(self): For full documentation refer to :obj:`numpy.ndarray.ndim`. - Parameters - ---------- - a : {dpnp.ndarray, usm_ndarray} - Input array. - Returns ------- number_of_dimensions : int @@ -1423,11 +1418,6 @@ def size(self): """ Number of elements in the array. - Parameters - ---------- - a : {dpnp.ndarray, usm_ndarray} - Input array. - Returns ------- element_count : int