From 9fa9077ecd91dbde74af2c9f2ecf7e6b29c651a0 Mon Sep 17 00:00:00 2001 From: Anton <100830759+antonwolfy@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:00:12 +0200 Subject: [PATCH] Backport gh-2034 (#2039) * Fix failing test for `dpnp.append` when no fp64 for device (#2034) * Fix test for dpnp.append with was failing with no fp64 support * Update docstring for dpnp.append and dpnp.asarray_chkfinite --------- Co-authored-by: vtavana <120411540+vtavana@users.noreply.github.com> * Update CHANGELOG --------- Co-authored-by: vtavana <120411540+vtavana@users.noreply.github.com> --- CHANGELOG.md | 4 + dpnp/dpnp_iface_manipulation.py | 176 +++++++++--------- .../manipulation_tests/test_add_remove.py | 2 +- 3 files changed, 93 insertions(+), 89 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7535c186b9..368fe3f0df8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,11 +97,15 @@ In addition, this release completes implementation of `dpnp.fft` module and adds * Extended `dpnp.heaviside` to support `order` and `out` keyword arguments by writing dedicated kernel for it [#2008](https://github.com/IntelPython/dpnp/pull/2008) * `dpnp` uses pybind11 2.13.5 [#2010](https://github.com/IntelPython/dpnp/pull/2010) * Add `COMPILER_VERSION_2025_OR_LATER` flag to be able to run `dpnp.fft` module with both 2024.2 and 2025.0 versions of the compiler [#2025](https://github.com/IntelPython/dpnp/pull/2025) +* Cleaned up an implementation of `dpnp.gradient` by removing obsolete TODO which is not going to be done [#2032](https://github.com/IntelPython/dpnp/pull/2032) +* Updated `Array Manipulation Routines` page in documentation to add missing functions and to remove duplicate entries [#2033](https://github.com/IntelPython/dpnp/pull/2033) ### Fixed * Resolved an issue with `dpnp.matmul` when an f_contiguous `out` keyword is passed to the the function [#1872](https://github.com/IntelPython/dpnp/pull/1872) * Resolved a possible race condition in `dpnp.inv` [#1940](https://github.com/IntelPython/dpnp/pull/1940) +* Resolved an issue with failing tests for `dpnp.append` when running on a device without fp64 support [#2034](https://github.com/IntelPython/dpnp/pull/2034) + ## [0.15.0] - 05/25/2024 diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index be9765c3420..ee3e987fb6a 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -297,7 +297,7 @@ def append(arr, values, axis=None): out : dpnp.ndarray A copy of `arr` with `values` appended to `axis`. Note that `append` does not occur in-place: a new array is allocated and - filled. If `axis` is None, `out` is a flattened array. + filled. If `axis` is ``None``, `out` is a flattened array. See Also -------- @@ -342,6 +342,89 @@ def append(arr, values, axis=None): return dpnp.concatenate((arr, values), axis=axis) +def array_split(ary, indices_or_sections, axis=0): + """ + Split an array into multiple sub-arrays. + + Please refer to the :obj:`dpnp.split` documentation. The only difference + between these functions is that ``dpnp.array_split`` allows + `indices_or_sections` to be an integer that does *not* equally divide the + axis. For an array of length l that should be split into n sections, it + returns ``l % n`` sub-arrays of size ``l//n + 1`` and the rest of size + ``l//n``. + + For full documentation refer to :obj:`numpy.array_split`. + + Parameters + ---------- + ary : {dpnp.ndarray, usm_ndarray} + Array to be divided into sub-arrays. + indices_or_sections : {int, sequence of ints} + If `indices_or_sections` is an integer, N, and array length is l, it + returns ``l % n`` sub-arrays of size ``l//n + 1`` and the rest of size + ``l//n``. + + If `indices_or_sections` is a sequence of sorted integers, the entries + indicate where along `axis` the array is split. + axis : int, optional + The axis along which to split. + Default: ``0``. + + Returns + ------- + sub-arrays : list of dpnp.ndarray + A list of sub arrays. Each array is a view of the corresponding input + array. + + See Also + -------- + :obj:`dpnp.split` : Split array into multiple sub-arrays of equal size. + + Examples + -------- + >>> import dpnp as np + >>> x = np.arange(8.0) + >>> np.array_split(x, 3) + [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7.])] + + >>> x = np.arange(9) + >>> np.array_split(x, 4) + [array([0, 1, 2]), array([3, 4]), array([5, 6]), array([7, 8])] + + """ + + dpnp.check_supported_arrays_type(ary) + n_tot = ary.shape[axis] + try: + # handle array case. + n_sec = len(indices_or_sections) + 1 + div_points = [0] + list(indices_or_sections) + [n_tot] + except TypeError: + # indices_or_sections is a scalar, not an array. + n_sec = int(indices_or_sections) + if n_sec <= 0: + raise ValueError("number sections must be larger than 0.") from None + n_each_sec, extras = numpy.divmod(n_tot, n_sec) + section_sizes = ( + [0] + extras * [n_each_sec + 1] + (n_sec - extras) * [n_each_sec] + ) + div_points = dpnp.array( + section_sizes, + dtype=dpnp.intp, + usm_type=ary.usm_type, + sycl_queue=ary.sycl_queue, + ).cumsum() + + sub_arys = [] + sary = dpnp.swapaxes(ary, axis, 0) + for i in range(n_sec): + st = div_points[i] + end = div_points[i + 1] + sub_arys.append(dpnp.swapaxes(sary[st:end], axis, 0)) + + return sub_arys + + def asarray_chkfinite( a, dtype=None, order=None, *, device=None, usm_type=None, sycl_queue=None ): @@ -356,12 +439,12 @@ def asarray_chkfinite( Input data, in any form that can be converted to an array. This includes lists, lists of tuples, tuples, tuples of tuples, tuples of lists and ndarrays. Success requires no NaNs or Infs. - dtype : str or dtype object, optional + dtype : {None, str, dtype object}, optional By default, the data-type is inferred from the input data. - default: ``None``. - order : {"C", "F", "A", "K"}, optional + Default: ``None``. + order : {None, "C", "F", "A", "K"}, optional Memory layout of the newly output array. - Default: "K". + Default: ``"K"``. device : {None, string, SyclDevice, SyclQueue}, optional An array API concept of device where the output array is created. The `device` can be ``None`` (the default), an OneAPI filter selector @@ -452,89 +535,6 @@ def asarray_chkfinite( return a -def array_split(ary, indices_or_sections, axis=0): - """ - Split an array into multiple sub-arrays. - - Please refer to the :obj:`dpnp.split` documentation. The only difference - between these functions is that ``dpnp.array_split`` allows - `indices_or_sections` to be an integer that does *not* equally divide the - axis. For an array of length l that should be split into n sections, it - returns ``l % n`` sub-arrays of size ``l//n + 1`` and the rest of size - ``l//n``. - - For full documentation refer to :obj:`numpy.array_split`. - - Parameters - ---------- - ary : {dpnp.ndarray, usm_ndarray} - Array to be divided into sub-arrays. - indices_or_sections : {int, sequence of ints} - If `indices_or_sections` is an integer, N, and array length is l, it - returns ``l % n`` sub-arrays of size ``l//n + 1`` and the rest of size - ``l//n``. - - If `indices_or_sections` is a sequence of sorted integers, the entries - indicate where along `axis` the array is split. - axis : int, optional - The axis along which to split. - Default: ``0``. - - Returns - ------- - sub-arrays : list of dpnp.ndarray - A list of sub arrays. Each array is a view of the corresponding input - array. - - See Also - -------- - :obj:`dpnp.split` : Split array into multiple sub-arrays of equal size. - - Examples - -------- - >>> import dpnp as np - >>> x = np.arange(8.0) - >>> np.array_split(x, 3) - [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7.])] - - >>> x = np.arange(9) - >>> np.array_split(x, 4) - [array([0, 1, 2]), array([3, 4]), array([5, 6]), array([7, 8])] - - """ - - dpnp.check_supported_arrays_type(ary) - n_tot = ary.shape[axis] - try: - # handle array case. - n_sec = len(indices_or_sections) + 1 - div_points = [0] + list(indices_or_sections) + [n_tot] - except TypeError: - # indices_or_sections is a scalar, not an array. - n_sec = int(indices_or_sections) - if n_sec <= 0: - raise ValueError("number sections must be larger than 0.") from None - n_each_sec, extras = numpy.divmod(n_tot, n_sec) - section_sizes = ( - [0] + extras * [n_each_sec + 1] + (n_sec - extras) * [n_each_sec] - ) - div_points = dpnp.array( - section_sizes, - dtype=dpnp.intp, - usm_type=ary.usm_type, - sycl_queue=ary.sycl_queue, - ).cumsum() - - sub_arys = [] - sary = dpnp.swapaxes(ary, axis, 0) - for i in range(n_sec): - st = div_points[i] - end = div_points[i + 1] - sub_arys.append(dpnp.swapaxes(sary[st:end], axis, 0)) - - return sub_arys - - def asfarray(a, dtype=None, *, device=None, usm_type=None, sycl_queue=None): """ Return an array converted to a float type. diff --git a/tests/third_party/cupy/manipulation_tests/test_add_remove.py b/tests/third_party/cupy/manipulation_tests/test_add_remove.py index 1e24175b6c4..c721f9ab31a 100644 --- a/tests/third_party/cupy/manipulation_tests/test_add_remove.py +++ b/tests/third_party/cupy/manipulation_tests/test_add_remove.py @@ -63,7 +63,7 @@ class TestAppend(unittest.TestCase): @testing.for_all_dtypes_combination( names=["dtype1", "dtype2"], no_bool=True ) - @testing.numpy_cupy_array_equal() + @testing.numpy_cupy_array_equal(type_check=has_support_aspect64()) def test(self, xp, dtype1, dtype2): a = testing.shaped_random((3, 4, 5), xp, dtype1) b = testing.shaped_random((6, 7), xp, dtype2)