From 7258b06d3951509c6cbcb680f9a431fc9d113c64 Mon Sep 17 00:00:00 2001 From: Anton <100830759+antonwolfy@users.noreply.github.com> Date: Fri, 13 Dec 2024 14:47:21 +0100 Subject: [PATCH 01/13] Bump SYCL compiler min version required (#2231) DPC++ compiler released 2025.0.4 version where `__SYCL_COMPILER_VERSION` is defined to `20241205`. But the fixes from #2211 and for `sycl::ext::intel::math::cyl_bessel_i0(x)` support weren't mapped there. Thus the PR proposes to bump `__SYCL_COMPILER_REDUCTION_PROPERTIES_SUPPORT` and `__SYCL_COMPILER_BESSEL_I0_SUPPORT` defines up to `20241210` value to exclude DPC++ compiler 2025.0.4 version. --- dpnp/backend/kernels/dpnp_krnl_common.cpp | 2 +- dpnp/backend/kernels/elementwise_functions/i0.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dpnp/backend/kernels/dpnp_krnl_common.cpp b/dpnp/backend/kernels/dpnp_krnl_common.cpp index 0c25716a236..051189578cf 100644 --- a/dpnp/backend/kernels/dpnp_krnl_common.cpp +++ b/dpnp/backend/kernels/dpnp_krnl_common.cpp @@ -40,7 +40,7 @@ * sycl::ext::oneapi::experimental::properties was added. */ #ifndef __SYCL_COMPILER_REDUCTION_PROPERTIES_SUPPORT -#define __SYCL_COMPILER_REDUCTION_PROPERTIES_SUPPORT 20241129 +#define __SYCL_COMPILER_REDUCTION_PROPERTIES_SUPPORT 20241210L #endif namespace mkl_blas = oneapi::mkl::blas; diff --git a/dpnp/backend/kernels/elementwise_functions/i0.hpp b/dpnp/backend/kernels/elementwise_functions/i0.hpp index ddb81d88cbc..51f6a6df591 100644 --- a/dpnp/backend/kernels/elementwise_functions/i0.hpp +++ b/dpnp/backend/kernels/elementwise_functions/i0.hpp @@ -32,7 +32,7 @@ * sycl::ext::intel::math::cyl_bessel_i0(x) is fully resolved. */ #ifndef __SYCL_COMPILER_BESSEL_I0_SUPPORT -#define __SYCL_COMPILER_BESSEL_I0_SUPPORT 20241114L +#define __SYCL_COMPILER_BESSEL_I0_SUPPORT 20241210L #endif #if __SYCL_COMPILER_VERSION >= __SYCL_COMPILER_BESSEL_I0_SUPPORT From 7e591e2bab2016d6c5dc94e092120d32b047e714 Mon Sep 17 00:00:00 2001 From: Anton <100830759+antonwolfy@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:27:53 +0100 Subject: [PATCH 02/13] mamba search does not accept --info option (#2236) The PR proposes to resolve the issue observing in GitHub actions where `mamba search --info` results into `The following argument was not expected: --info` error. The error started to be reported since `mamba==2.0.5` release. As a workaround it is proposed to switch to `conda search --info` command which works properly. Note, #2231 is tuned here to consider available DPC++ version on Windows. --- .github/workflows/conda-package.yml | 6 +++--- dpnp/backend/kernels/dpnp_krnl_common.cpp | 2 +- dpnp/backend/kernels/elementwise_functions/i0.hpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 8ff31e7205e..d7c67e679a2 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -148,7 +148,7 @@ jobs: - name: Test conda channel run: | - mamba search ${{ env.PACKAGE_NAME }} -c ${{ env.channel-path }} --override-channels --info --json > ${{ env.ver-json-path }} + conda search ${{ env.PACKAGE_NAME }} -c ${{ env.channel-path }} --override-channels --info --json > ${{ env.ver-json-path }} cat ${{ env.ver-json-path }} - name: Get package version @@ -182,7 +182,7 @@ jobs: id: run_tests_linux uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0 with: - timeout_minutes: 10 + timeout_minutes: 12 max_attempts: ${{ env.RUN_TESTS_MAX_ATTEMPTS }} retry_on: any command: | @@ -348,7 +348,7 @@ jobs: - name: Test conda channel run: | @echo on - mamba search ${{ env.PACKAGE_NAME }} -c ${{ env.channel-path }} --override-channels --info --json > ${{ env.ver-json-path }} + conda search ${{ env.PACKAGE_NAME }} -c ${{ env.channel-path }} --override-channels --info --json > ${{ env.ver-json-path }} - name: Dump version.json run: more ${{ env.ver-json-path }} diff --git a/dpnp/backend/kernels/dpnp_krnl_common.cpp b/dpnp/backend/kernels/dpnp_krnl_common.cpp index 051189578cf..22f50986c2c 100644 --- a/dpnp/backend/kernels/dpnp_krnl_common.cpp +++ b/dpnp/backend/kernels/dpnp_krnl_common.cpp @@ -40,7 +40,7 @@ * sycl::ext::oneapi::experimental::properties was added. */ #ifndef __SYCL_COMPILER_REDUCTION_PROPERTIES_SUPPORT -#define __SYCL_COMPILER_REDUCTION_PROPERTIES_SUPPORT 20241210L +#define __SYCL_COMPILER_REDUCTION_PROPERTIES_SUPPORT 20241208L #endif namespace mkl_blas = oneapi::mkl::blas; diff --git a/dpnp/backend/kernels/elementwise_functions/i0.hpp b/dpnp/backend/kernels/elementwise_functions/i0.hpp index 51f6a6df591..68bc41ea377 100644 --- a/dpnp/backend/kernels/elementwise_functions/i0.hpp +++ b/dpnp/backend/kernels/elementwise_functions/i0.hpp @@ -32,7 +32,7 @@ * sycl::ext::intel::math::cyl_bessel_i0(x) is fully resolved. */ #ifndef __SYCL_COMPILER_BESSEL_I0_SUPPORT -#define __SYCL_COMPILER_BESSEL_I0_SUPPORT 20241210L +#define __SYCL_COMPILER_BESSEL_I0_SUPPORT 20241208L #endif #if __SYCL_COMPILER_VERSION >= __SYCL_COMPILER_BESSEL_I0_SUPPORT From fc249e15ebe8cde6520b42273c717a4150ec68de Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Mon, 2 Dec 2024 13:51:58 -0800 Subject: [PATCH 03/13] update tests for newly added integr dtypes (int8, int16, uint8-uint64) --- .github/workflows/conda-package.yml | 8 +- dpnp/dpnp_iface_linearalgebra.py | 29 +- dpnp/dpnp_iface_nanfunctions.py | 4 +- dpnp/fft/dpnp_utils_fft.py | 5 +- dpnp/tests/helper.py | 32 +-- dpnp/tests/test_amin_amax.py | 20 +- dpnp/tests/test_arraycreation.py | 14 +- dpnp/tests/test_bitwise.py | 3 +- dpnp/tests/test_fft.py | 5 +- dpnp/tests/test_histogram.py | 23 +- dpnp/tests/test_indexing.py | 226 ++++++++------- dpnp/tests/test_linalg.py | 17 +- dpnp/tests/test_manipulation.py | 6 +- dpnp/tests/test_mathematical.py | 257 +++++++++++------- dpnp/tests/test_nanfunctions.py | 2 +- dpnp/tests/test_ndarray.py | 4 + dpnp/tests/test_outer.py | 6 +- dpnp/tests/test_product.py | 79 +++--- dpnp/tests/test_sort.py | 9 +- dpnp/tests/test_strides.py | 48 +++- dpnp/tests/test_sum.py | 22 +- dpnp/tests/test_umath.py | 32 ++- dpnp/tests/third_party/cupy/testing/_loops.py | 25 +- 23 files changed, 521 insertions(+), 355 deletions(-) diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index d7c67e679a2..1afca13378d 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -107,7 +107,7 @@ jobs: strategy: matrix: - python: ['3.9', '3.10', '3.11', '3.12'] + python: ['3.9', '3.10', '3.11'] continue-on-error: true @@ -193,7 +193,7 @@ jobs: python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests test_linux_all_dtypes: - name: Test ['ubuntu-latest', python='${{ matrix.python }}'] + name: Test ['ubuntu-latest-all-dtypes', python='${{ matrix.python }}'] needs: build @@ -289,7 +289,7 @@ jobs: strategy: matrix: - python: ['3.9', '3.10', '3.11', '3.12'] + python: ['3.9', '3.10', '3.11'] continue-on-error: true @@ -409,7 +409,7 @@ jobs: python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests test_windows_all_dtypes: - name: Test ['windows-2019', python='${{ matrix.python }}'] + name: Test ['windows-2019-all-dtypes', python='${{ matrix.python }}'] needs: build diff --git a/dpnp/dpnp_iface_linearalgebra.py b/dpnp/dpnp_iface_linearalgebra.py index bb89f0769d9..332085195d9 100644 --- a/dpnp/dpnp_iface_linearalgebra.py +++ b/dpnp/dpnp_iface_linearalgebra.py @@ -37,10 +37,12 @@ """ +# pylint: disable=no-name-in-module import numpy import dpnp +from .dpnp_utils import map_dtype_to_device from .dpnp_utils.dpnp_utils_einsum import dpnp_einsum from .dpnp_utils.dpnp_utils_linearalgebra import ( dpnp_dot, @@ -64,6 +66,17 @@ ] +# TODO: implement a specific scalar-array kernel +def _call_multiply(a, b, out=None): + """Call multiply function for special cases of scalar-array dots.""" + + sc, arr = (a, b) if dpnp.isscalar(a) else (b, a) + sc_dtype = map_dtype_to_device(type(sc), arr.sycl_device) + res_dtype = dpnp.result_type(sc_dtype, arr) + res = dpnp.multiply(a, b, dtype=res_dtype) + return dpnp.get_result_array(res, out, casting="no") + + def dot(a, b, out=None): """ Dot product of `a` and `b`. @@ -137,8 +150,7 @@ def dot(a, b, out=None): raise ValueError("Only C-contiguous array is acceptable.") if dpnp.isscalar(a) or dpnp.isscalar(b): - # TODO: use specific scalar-vector kernel - return dpnp.multiply(a, b, out=out) + return _call_multiply(a, b, out=out) a_ndim = a.ndim b_ndim = b.ndim @@ -627,8 +639,7 @@ def inner(a, b): dpnp.check_supported_arrays_type(a, b, scalar_type=True) if dpnp.isscalar(a) or dpnp.isscalar(b): - # TODO: use specific scalar-vector kernel - return dpnp.multiply(a, b) + return _call_multiply(a, b) if a.ndim == 0 or b.ndim == 0: # TODO: use specific scalar-vector kernel @@ -706,8 +717,7 @@ def kron(a, b): dpnp.check_supported_arrays_type(a, b, scalar_type=True) if dpnp.isscalar(a) or dpnp.isscalar(b): - # TODO: use specific scalar-vector kernel - return dpnp.multiply(a, b) + return _call_multiply(a, b) a_ndim = a.ndim b_ndim = b.ndim @@ -1043,8 +1053,7 @@ def tensordot(a, b, axes=2): raise ValueError( "One of the inputs is scalar, axes should be zero." ) - # TODO: use specific scalar-vector kernel - return dpnp.multiply(a, b) + return _call_multiply(a, b) return dpnp_tensordot(a, b, axes=axes) @@ -1107,13 +1116,13 @@ def vdot(a, b): if b.size != 1: raise ValueError("The second array should be of size one.") a_conj = numpy.conj(a) - return dpnp.multiply(a_conj, b) + return _call_multiply(a_conj, b) if dpnp.isscalar(b): if a.size != 1: raise ValueError("The first array should be of size one.") a_conj = dpnp.conj(a) - return dpnp.multiply(a_conj, b) + return _call_multiply(a_conj, b) if a.ndim == 1 and b.ndim == 1: return dpnp_dot(a, b, out=None, conjugate=True) diff --git a/dpnp/dpnp_iface_nanfunctions.py b/dpnp/dpnp_iface_nanfunctions.py index a808617469f..950e86b9d51 100644 --- a/dpnp/dpnp_iface_nanfunctions.py +++ b/dpnp/dpnp_iface_nanfunctions.py @@ -987,7 +987,7 @@ def nanstd( ddof : {int, float}, optional Means Delta Degrees of Freedom. The divisor used in calculations is ``N - ddof``, where ``N`` the number of non-NaN elements. - Default: `0.0`. + Default: ``0.0``. keepdims : {None, bool}, optional If ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions, so that the returned array remains @@ -1087,7 +1087,7 @@ def nanvar( ddof : {int, float}, optional Means Delta Degrees of Freedom. The divisor used in calculations is ``N - ddof``, where ``N`` represents the number of non-NaN elements. - Default: `0.0`. + Default: ``0.0``. keepdims : {None, bool}, optional If ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions, so that the returned array remains diff --git a/dpnp/fft/dpnp_utils_fft.py b/dpnp/fft/dpnp_utils_fft.py index e2855acd60c..95ad5b7bbb8 100644 --- a/dpnp/fft/dpnp_utils_fft.py +++ b/dpnp/fft/dpnp_utils_fft.py @@ -282,7 +282,10 @@ def _copy_array(x, complex_input): # r2c FFT, if input is integer or float16 dtype, convert to # float32 or float64 depending on device capabilities copy_flag = True - dtype = map_dtype_to_device(dpnp.float64, x.sycl_device) + if dtype in [dpnp.float16]: + dtype = dpnp.float32 + else: + dtype = map_dtype_to_device(dpnp.float64, x.sycl_device) if copy_flag: x_copy = dpnp.empty_like(x, dtype=dtype, order="C") diff --git a/dpnp/tests/helper.py b/dpnp/tests/helper.py index 44945dc4c8b..f7bb9cfc934 100644 --- a/dpnp/tests/helper.py +++ b/dpnp/tests/helper.py @@ -85,24 +85,19 @@ def assert_dtype_allclose( assert dpnp_arr.dtype == numpy_arr.dtype -def get_integer_dtypes(): +def get_integer_dtypes(no_unsigned=False): """ Build a list of integer types supported by DPNP. """ + dtypes = [dpnp.int32, dpnp.int64] + if config.all_int_types: - return [ - dpnp.int8, - dpnp.int16, - dpnp.int32, - dpnp.int64, - dpnp.uint8, - dpnp.uint16, - dpnp.uint32, - dpnp.uint64, - ] + dtypes += [dpnp.int8, dpnp.int16] + if not no_unsigned: + dtypes += [dpnp.uint8, dpnp.uint16, dpnp.uint32, dpnp.uint64] - return [dpnp.int32, dpnp.int64] + return dtypes def get_complex_dtypes(device=None): @@ -152,12 +147,14 @@ def get_all_dtypes( no_float16=True, no_complex=False, no_none=False, - device=None, xfail_dtypes=None, exclude=None, + no_unsigned=False, + device=None, ): """ - Build a list of types supported by DPNP based on input flags and device capabilities. + Build a list of types supported by DPNP based on + input flags and device capabilities. """ dev = dpctl.select_default_device() if device is None else device @@ -166,7 +163,7 @@ def get_all_dtypes( dtypes = [dpnp.bool] if not no_bool else [] # add integer types - dtypes.extend(get_integer_dtypes()) + dtypes.extend(get_integer_dtypes(no_unsigned=no_unsigned)) # add floating types dtypes.extend(get_float_dtypes(no_float16=no_float16, device=dev)) @@ -239,10 +236,13 @@ def generate_random_numpy_array( seed_value = 42 numpy.random.seed(seed_value) + if numpy.issubdtype(dtype, numpy.unsignedinteger): + low = 0 + # dtype=int is needed for 0d arrays size = numpy.prod(shape, dtype=int) a = numpy.random.uniform(low, high, size).astype(dtype) - if numpy.issubdtype(a.dtype, numpy.complexfloating): + if numpy.issubdtype(dtype, numpy.complexfloating): a += 1j * numpy.random.uniform(low, high, size) a = a.reshape(shape) diff --git a/dpnp/tests/test_amin_amax.py b/dpnp/tests/test_amin_amax.py index 1b119ab225b..1052fe7d77e 100644 --- a/dpnp/tests/test_amin_amax.py +++ b/dpnp/tests/test_amin_amax.py @@ -17,8 +17,10 @@ def test_amax_amin(func, keepdims, dtype): [[-2.0, 5.0], [-2, -1.2]], [[1.0, -2.0], [5.0, -1.1]], ], - dtype=dtype, ) + if numpy.issubdtype(dtype, numpy.unsignedinteger): + a = numpy.abs(a) + a = a.astype(dtype) ia = dpnp.array(a) for axis in range(len(a)): @@ -28,20 +30,20 @@ def test_amax_amin(func, keepdims, dtype): def _get_min_max_input(type, shape): - size = 1 - for i in range(len(shape)): - size *= shape[i] - + size = numpy.prod(shape) a = numpy.arange(size, dtype=type) - a[int(size / 2)] = size * size - a[int(size / 3)] = -(size * size) + a[int(size / 2)] = size + 5 + if numpy.issubdtype(type, numpy.unsignedinteger): + a[int(size / 3)] = size + else: + a[int(size / 3)] = -(size + 5) return a.reshape(shape) @pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True)) @pytest.mark.parametrize( - "shape", [(4,), (2, 3), (4, 5, 6)], ids=["(4,)", "(2,3)", "(4,5,6)"] + "shape", [(4,), (2, 3), (4, 5, 6)], ids=["(4,)", "(2, 3)", "(4, 5, 6)"] ) def test_amax_diff_shape(dtype, shape): a = _get_min_max_input(dtype, shape) @@ -59,7 +61,7 @@ def test_amax_diff_shape(dtype, shape): @pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True)) @pytest.mark.parametrize( - "shape", [(4,), (2, 3), (4, 5, 6)], ids=["(4,)", "(2,3)", "(4,5,6)"] + "shape", [(4,), (2, 3), (4, 5, 6)], ids=["(4,)", "(2, 3)", "(4, 5, 6)"] ) def test_amin_diff_shape(dtype, shape): a = _get_min_max_input(dtype, shape) diff --git a/dpnp/tests/test_arraycreation.py b/dpnp/tests/test_arraycreation.py index 445c348a95d..b321401a56e 100644 --- a/dpnp/tests/test_arraycreation.py +++ b/dpnp/tests/test_arraycreation.py @@ -182,10 +182,12 @@ def test_exception_subok(func, args): "dtype", get_all_dtypes(no_bool=True, no_float16=False) ) def test_arange(start, stop, step, dtype): - rtol_mult = 2 - if dpnp.issubdtype(dtype, dpnp.float16): - # numpy casts to float32 type when computes float16 data - rtol_mult = 4 + if numpy.issubdtype(dtype, numpy.unsignedinteger): + start = abs(start) + stop = abs(stop) if stop else None + + # numpy casts to float32 type when computes float16 data + rtol_mult = 4 if dpnp.issubdtype(dtype, dpnp.float16) else 2 func = lambda xp: xp.arange(start, stop=stop, step=step, dtype=dtype) @@ -701,7 +703,7 @@ def test_dpctl_tensor_input(func, args): @pytest.mark.parametrize("start", [0, -5, 10, -2.5, 9.7]) -@pytest.mark.parametrize("stop", [0, 10, -2, 20.5, 1000]) +@pytest.mark.parametrize("stop", [0, 10, -2, 20.5, 120]) @pytest.mark.parametrize( "num", [1, 5, numpy.array(10), dpnp.array(17), dpt.asarray(100)], @@ -850,7 +852,7 @@ def test_space_num_error(): @pytest.mark.parametrize("endpoint", [True, False]) def test_geomspace(sign, dtype, num, endpoint): start = 2 * sign - stop = 256 * sign + stop = 127 * sign func = lambda xp: xp.geomspace( start, stop, num, endpoint=endpoint, dtype=dtype diff --git a/dpnp/tests/test_bitwise.py b/dpnp/tests/test_bitwise.py index 41f10c02354..33e327218d4 100644 --- a/dpnp/tests/test_bitwise.py +++ b/dpnp/tests/test_bitwise.py @@ -167,7 +167,8 @@ def test_bitwise_aliase2(self, lhs, rhs, dtype): @pytest.mark.parametrize("dtype", get_integer_dtypes()) def test_invert_out(dtype): - np_a = numpy.arange(-5, 5, dtype=dtype) + low = 0 if numpy.issubdtype(dtype, numpy.unsignedinteger) else -5 + np_a = numpy.arange(low, 5, dtype=dtype) dp_a = inp.array(np_a) expected = numpy.invert(np_a) diff --git a/dpnp/tests/test_fft.py b/dpnp/tests/test_fft.py index 8915daa43e2..88ef7011b1b 100644 --- a/dpnp/tests/test_fft.py +++ b/dpnp/tests/test_fft.py @@ -816,7 +816,10 @@ def test_rfft_1D(self, dtype, n, norm): result = dpnp.fft.rfft(a, n=n, norm=norm) expected = numpy.fft.rfft(a_np, n=n, norm=norm) - assert_dtype_allclose(result, expected, check_only_type_kind=True) + factor = 120 if dtype in [dpnp.int8, dpnp.uint8] else 8 + assert_dtype_allclose( + result, expected, factor=factor, check_only_type_kind=True + ) @pytest.mark.parametrize("n", [None, 5, 20]) @pytest.mark.parametrize("norm", [None, "backward", "forward", "ortho"]) diff --git a/dpnp/tests/test_histogram.py b/dpnp/tests/test_histogram.py index 6a4e8abceb6..8950ee8df4b 100644 --- a/dpnp/tests/test_histogram.py +++ b/dpnp/tests/test_histogram.py @@ -44,6 +44,9 @@ class TestDigitize: ], ) def test_digitize(self, x, bins, dtype, right): + if numpy.issubdtype(dtype, numpy.unsignedinteger) and bins[0] == -4: + x = numpy.abs(x) + bins = numpy.array([0, 2, 4, 6, 8]) x = x.astype(dtype) bins = bins.astype(dtype) x_dp = dpnp.array(x) @@ -527,18 +530,26 @@ def test_rand_data(self, dtype): v = numpy.random.randint(0, upper_bound, size=n, dtype=dtype) iv = dpnp.array(v) - expected_hist = numpy.bincount(v) - result_hist = dpnp.bincount(iv) - assert_array_equal(result_hist, expected_hist) + if numpy.issubdtype(dtype, numpy.uint64): + assert_raises(TypeError, numpy.bincount, v) + assert_raises(ValueError, dpnp.bincount, iv) + else: + expected_hist = numpy.bincount(v) + result_hist = dpnp.bincount(iv) + assert_array_equal(result_hist, expected_hist) @pytest.mark.parametrize("dtype", get_integer_dtypes()) def test_arange_data(self, dtype): v = numpy.arange(100).astype(dtype) iv = dpnp.array(v) - expected_hist = numpy.bincount(v) - result_hist = dpnp.bincount(iv) - assert_array_equal(result_hist, expected_hist) + if numpy.issubdtype(dtype, numpy.uint64): + assert_raises(TypeError, numpy.bincount, v) + assert_raises(ValueError, dpnp.bincount, iv) + else: + expected_hist = numpy.bincount(v) + result_hist = dpnp.bincount(iv) + assert_array_equal(result_hist, expected_hist) @pytest.mark.parametrize("xp", [numpy, dpnp]) def test_negative_values(self, xp): diff --git a/dpnp/tests/test_indexing.py b/dpnp/tests/test_indexing.py index 61b91015461..93c67786b95 100644 --- a/dpnp/tests/test_indexing.py +++ b/dpnp/tests/test_indexing.py @@ -43,12 +43,12 @@ class TestDiagonal: "shape", [(2, 2), (3, 3), (2, 5), (3, 2, 2), (2, 2, 2, 2), (2, 2, 2, 3)], ids=[ - "(2,2)", - "(3,3)", - "(2,5)", - "(3,2,2)", - "(2,2,2,2)", - "(2,2,2,3)", + "(2, 2)", + "(3, 3)", + "(2, 5)", + "(3, 2, 2)", + "(2, 2, 2, 2)", + "(2, 2, 2, 3)", ], ) def test_diagonal_offset(self, shape, dtype, offset): @@ -122,8 +122,14 @@ def test_extract(self, dt): @pytest.mark.parametrize("a_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("cond_dt", get_all_dtypes(no_none=True)) def test_extract_diff_dtypes(self, a_dt, cond_dt): - a = numpy.array([-2, -1, 0, 1, 2, 3], dtype=a_dt) - cond = numpy.array([1, -1, 2, 0, -2, 3], dtype=cond_dt) + x = [-2, -1, 0, 1, 2, 3] + y = [1, -1, 2, 0, -2, 3] + if numpy.issubdtype(a_dt, numpy.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=a_dt) + if numpy.issubdtype(cond_dt, numpy.unsignedinteger): + y = numpy.abs(y) + cond = numpy.array(y, dtype=cond_dt) ia, icond = dpnp.array(a), dpnp.array(cond) result = dpnp.extract(icond, ia) @@ -132,7 +138,10 @@ def test_extract_diff_dtypes(self, a_dt, cond_dt): @pytest.mark.parametrize("a_dt", get_all_dtypes(no_none=True)) def test_extract_list_cond(self, a_dt): - a = numpy.array([-2, -1, 0, 1, 2, 3], dtype=a_dt) + x = [-2, -1, 0, 1, 2, 3] + if numpy.issubdtype(a_dt, numpy.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=a_dt) cond = [1, -1, 2, 0, -2, 3] ia = dpnp.array(a) @@ -165,7 +174,7 @@ def test_place_diff_dtypes(self, a_dt, mask_dt, vals_dt): dtype=mask_dt, ) vals = numpy.array( - [100, 200, 300, 400, 500, 600, 800, 900], dtype=vals_dt + [101, 102, 103, 104, 105, 106, 108, 109], dtype=vals_dt ) ia, imask, ivals = dpnp.array(a), dpnp.array(mask), dpnp.array(vals) @@ -385,7 +394,10 @@ def test_0d(self, val): @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) def test_1d(self, dtype): - a = numpy.array([1, 0, 2, -1, 0, 0, 8], dtype=dtype) + x = [1, 0, 2, -1, 0, 0, 8] + if numpy.issubdtype(dtype, numpy.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=dtype) ia = dpnp.array(a) np_res = numpy.nonzero(a) @@ -437,21 +449,26 @@ def test_array_method(self, dtype): class TestPut: @pytest.mark.parametrize("a_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( - "indices", [[0, 2], [-5, 4]], ids=["[0, 2]", "[-5, 4]"] + "indices", [[0, 2], [-3, 4]], ids=["[0, 2]", "[-3, 4]"] ) @pytest.mark.parametrize("ind_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( "vals", [0, [1, 2], (2, 2), dpnp.array([1, 2])], - ids=["0", "[1, 2]", "(2, 2)", "dpnp.array([1,2])"], + ids=["0", "[1, 2]", "(2, 2)", "dpnp.array([1, 2])"], ) @pytest.mark.parametrize("mode", ["clip", "wrap"]) def test_input_1d(self, a_dt, indices, ind_dt, vals, mode): - a = numpy.array([-2, -1, 0, 1, 2], dtype=a_dt) + x = [-2, -1, 0, 1, 2] + if numpy.issubdtype(a_dt, numpy.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=a_dt) b = numpy.copy(a) ia = dpnp.array(a) ib = dpnp.array(b) + if numpy.issubdtype(ind_dt, numpy.unsignedinteger): + indices = numpy.abs(indices) ind = numpy.array(indices, dtype=ind_dt) if ind_dt == dpnp.bool and ind.all(): ind[0] = False # to get rid of duplicate indices @@ -465,6 +482,18 @@ def test_input_1d(self, a_dt, indices, ind_dt, vals, mode): b.put(ind, vals, mode=mode) ib.put(iind, vals, mode=mode) assert_array_equal(ib, b) + elif numpy.issubdtype(ind_dt, numpy.uint64): + # For this special case, NumPy raises an error but dpnp works + assert_raises(TypeError, numpy.put, a, ind, vals, mode=mode) + assert_raises(TypeError, b.put, ind, vals, mode=mode) + + numpy.put(a, ind.astype(numpy.int64), vals, mode=mode) + dpnp.put(ia, iind, vals, mode=mode) + assert_array_equal(ia, a) + + b.put(ind.astype(numpy.int64), vals, mode=mode) + ib.put(iind, vals, mode=mode) + assert_array_equal(ib, b) else: assert_raises(TypeError, numpy.put, a, ind, vals, mode=mode) assert_raises(TypeError, dpnp.put, ia, iind, vals, mode=mode) @@ -475,30 +504,35 @@ def test_input_1d(self, a_dt, indices, ind_dt, vals, mode): @pytest.mark.parametrize("a_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( "indices", - [ - [0, 7], - [3, 4], - [-9, 8], - ], - ids=[ - "[0, 7]", - "[3, 4]", - "[-9, 8]", - ], + [[0, 7], [3, 4], [-7, 8]], + ids=["[0, 7]", "[3, 4]", "[-7, 8]"], ) @pytest.mark.parametrize("ind_dt", get_integer_dtypes()) - @pytest.mark.parametrize("vals", [[10, 20]], ids=["[10, 20]"]) @pytest.mark.parametrize("mode", ["clip", "wrap"]) - def test_input_2d(self, a_dt, indices, ind_dt, vals, mode): - a = numpy.array([[-1, 0, 1], [-2, -3, -4], [2, 3, 4]], dtype=a_dt) + def test_input_2d(self, a_dt, indices, ind_dt, mode): + x = [[-1, 0, 1], [-2, -3, -4], [2, 3, 4]] + if numpy.issubdtype(a_dt, numpy.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=a_dt) ia = dpnp.array(a) + vals = [10, 20] + if numpy.issubdtype(ind_dt, numpy.unsignedinteger): + indices = numpy.abs(indices) ind = numpy.array(indices, dtype=ind_dt) iind = dpnp.array(ind) - numpy.put(a, ind, vals, mode=mode) - dpnp.put(ia, iind, vals, mode=mode) - assert_array_equal(ia, a) + if numpy.issubdtype(ind_dt, numpy.uint64): + # For this special case, NumPy raises an error but dpnp works + assert_raises(TypeError, numpy.put, a, ind, vals, mode=mode) + + numpy.put(a, ind.astype(numpy.int64), vals, mode=mode) + dpnp.put(ia, iind, vals, mode=mode) + assert_array_equal(ia, a) + else: + numpy.put(a, ind, vals, mode=mode) + dpnp.put(ia, iind, vals, mode=mode) + assert_array_equal(ia, a) def test_indices_2d(self): a = numpy.arange(5) @@ -536,17 +570,7 @@ def test_empty_input(self, mode): with pytest.raises(IndexError): empty.put(1, 1, mode=mode) - @pytest.mark.parametrize( - "shape", - [ - (3,), - (4,), - ], - ids=[ - "(3,)", - "(4,)", - ], - ) + @pytest.mark.parametrize("shape", [(3,), (4,)], ids=["(3,)", "(4,)"]) @pytest.mark.parametrize("mode", ["clip", "wrap"]) def test_invalid_shape(self, shape, mode): a = dpnp.arange(7) @@ -558,17 +582,7 @@ def test_invalid_shape(self, shape, mode): @pytest.mark.parametrize("xp", [dpnp, numpy]) @pytest.mark.parametrize( - "axis", - [ - 1.0, - (0,), - [0, 1], - ], - ids=[ - "1.0", - "(0,)", - "[0, 1]", - ], + "axis", [1.0, (0,), [0, 1]], ids=["1.0", "(0,)", "[0, 1]"] ) def test_invalid_axis(self, xp, axis): a = xp.arange(6).reshape(2, 3) @@ -599,7 +613,8 @@ def test_replace_max(self, arr_dt, axis): # replace the max with a small value i_max = _add_keepdims(dpnp.argmax)(a, axis=axis) - dpnp.put_along_axis(a, i_max, -99, axis=axis) + val = 0 if numpy.issubdtype(arr_dt, numpy.unsignedinteger) else -99 + dpnp.put_along_axis(a, i_max, val, axis=axis) # find the new minimum, which should max i_min = _add_keepdims(dpnp.argmin)(a, axis=axis) @@ -613,8 +628,8 @@ def test_replace_max(self, arr_dt, axis): @pytest.mark.parametrize( "values", [ - 777, - [100, 200, 300, 400], + 77, + [101, 102, 103, 104], (42,), range(4), numpy.arange(4), @@ -655,9 +670,10 @@ def test_broadcast(self, arr_dt, idx_dt): ind = numpy.arange(10, dtype=idx_dt).reshape((1, 2, 5)) % 4 ia, iind = dpnp.array(a), dpnp.array(ind) - numpy.put_along_axis(a, ind, 20, axis=1) - dpnp.put_along_axis(ia, iind, 20, axis=1) - assert_array_equal(ia, a) + if numpy.issubdtype(idx_dt, numpy.uint64): + numpy.put_along_axis(a, ind, 20, axis=1) + dpnp.put_along_axis(ia, iind, 20, axis=1) + assert_array_equal(ia, a) def test_mode_wrap(self): a = numpy.array([-2, -1, 0, 1, 2]) @@ -687,11 +703,16 @@ class TestTake: @pytest.mark.parametrize("a_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("ind_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( - "indices", [[-2, 2], [-5, 4]], ids=["[-2, 2]", "[-5, 4]"] + "indices", [[-2, 2], [-4, 4]], ids=["[-2, 2]", "[-4, 4]"] ) @pytest.mark.parametrize("mode", ["clip", "wrap"]) def test_1d(self, a_dt, ind_dt, indices, mode): - a = numpy.array([-2, -1, 0, 1, 2], dtype=a_dt) + x = [-2, -1, 0, 1, 2] + if numpy.issubdtype(a_dt, numpy.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=a_dt) + if numpy.issubdtype(ind_dt, numpy.unsignedinteger): + indices = numpy.abs(indices) ind = numpy.array(indices, dtype=ind_dt) ia, iind = dpnp.array(a), dpnp.array(ind) @@ -699,6 +720,13 @@ def test_1d(self, a_dt, ind_dt, indices, mode): result = dpnp.take(ia, iind, mode=mode) expected = numpy.take(a, ind, mode=mode) assert_array_equal(result, expected) + elif numpy.issubdtype(ind_dt, numpy.uint64): + # For this special case, although casting `ind_dt` to numpy.intp + # is not safe, dpnp do not raise an error + # NumPy only raises an error on Windows + result = dpnp.take(ia, iind, mode=mode) + expected = numpy.take(a, ind.astype(numpy.int64), mode=mode) + assert_array_equal(result, expected) else: assert_raises(TypeError, ia.take, iind, mode=mode) assert_raises(TypeError, a.take, ind, mode=mode) @@ -706,28 +734,43 @@ def test_1d(self, a_dt, ind_dt, indices, mode): @pytest.mark.parametrize("a_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("ind_dt", get_integer_dtypes()) @pytest.mark.parametrize( - "indices", [[-1, 0], [-3, 2]], ids=["[-1, 0]", "[-3, 2]"] + "indices", [[-1, 0], [-2, 2]], ids=["[-1, 0]", "[-2, 2]"] ) @pytest.mark.parametrize("mode", ["clip", "wrap"]) - @pytest.mark.parametrize("axis", [0, 1], ids=["0", "1"]) + @pytest.mark.parametrize("axis", [0, 1]) def test_2d(self, a_dt, ind_dt, indices, mode, axis): - a = numpy.array([[-1, 0, 1], [-2, -3, -4], [2, 3, 4]], dtype=a_dt) + x = [[-1, 0, 1], [-2, -3, -4], [2, 3, 4]] + if numpy.issubdtype(a_dt, numpy.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=a_dt) + if numpy.issubdtype(ind_dt, numpy.unsignedinteger): + indices = numpy.abs(indices) ind = numpy.array(indices, dtype=ind_dt) ia, iind = dpnp.array(a), dpnp.array(ind) - result = ia.take(iind, axis=axis, mode=mode) - expected = a.take(ind, axis=axis, mode=mode) - assert_array_equal(result, expected) + if numpy.issubdtype(ind_dt, numpy.uint64): + # For this special case, NumPy raises an error on Windows + result = ia.take(iind, axis=axis, mode=mode) + expected = a.take(ind.astype(numpy.int64), axis=axis, mode=mode) + assert_array_equal(result, expected) + else: + result = ia.take(iind, axis=axis, mode=mode) + expected = a.take(ind, axis=axis, mode=mode) + assert_array_equal(result, expected) @pytest.mark.parametrize("a_dt", get_all_dtypes(no_none=True)) - @pytest.mark.parametrize("indices", [[-5, 5]], ids=["[-5, 5]"]) @pytest.mark.parametrize("mode", ["clip", "wrap"]) - def test_over_index(self, a_dt, indices, mode): - a = dpnp.array([-2, -1, 0, 1, 2], dtype=a_dt) - ind = dpnp.array(indices, dtype=numpy.intp) + def test_over_index(self, a_dt, mode): + x = [-2, -1, 0, 1, 2] + y = [-2, 2] + if numpy.issubdtype(a_dt, numpy.unsignedinteger): + x = numpy.abs(x) + y = numpy.abs(y) + a = dpnp.array(x, dtype=a_dt) + ind = dpnp.array([-5, 5], dtype=numpy.intp) result = dpnp.take(a, ind, mode=mode) - expected = dpnp.array([-2, 2], dtype=a.dtype) + expected = dpnp.array(y, dtype=a.dtype) assert_array_equal(result, expected) @pytest.mark.parametrize("xp", [numpy, dpnp]) @@ -887,7 +930,7 @@ def test_choose(): assert_array_equal(expected, result) -@pytest.mark.parametrize("val", [-1, 0, 1], ids=["-1", "0", "1"]) +@pytest.mark.parametrize("val", [-1, 0, 1]) @pytest.mark.parametrize( "array", [ @@ -936,7 +979,7 @@ def test_fill_diagonal(array, val): ], ) @pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True)) -@pytest.mark.parametrize("sparse", [True, False], ids=["True", "False"]) +@pytest.mark.parametrize("sparse", [True, False]) def test_indices(dimension, dtype, sparse): expected = numpy.indices(dimension, dtype=dtype, sparse=sparse) result = dpnp.indices(dimension, dtype=dtype, sparse=sparse) @@ -944,7 +987,6 @@ def test_indices(dimension, dtype, sparse): assert_array_equal(Xnp, X) -@pytest.mark.parametrize("vals", [[100, 200]], ids=["[100, 200]"]) @pytest.mark.parametrize( "mask", [ @@ -963,12 +1005,12 @@ def test_indices(dimension, dtype, sparse): [[[0, 0], [0, 0]], [[1, 2], [1, 2]], [[1, 2], [3, 4]]], ids=["[[0, 0], [0, 0]]", "[[1, 2], [1, 2]]", "[[1, 2], [3, 4]]"], ) -def test_putmask1(arr, mask, vals): +def test_putmask1(arr, mask): a = numpy.array(arr) ia = dpnp.array(a) m = numpy.array(mask) im = dpnp.array(m) - v = numpy.array(vals) + v = numpy.array([100, 200]) iv = dpnp.array(v) numpy.putmask(a, m, v) dpnp.putmask(ia, im, iv) @@ -1067,24 +1109,16 @@ def test_putmask3(arr, mask, vals): assert_array_equal(a, ia) -@pytest.mark.parametrize( - "m", [None, 0, 1, 2, 3, 4], ids=["None", "0", "1", "2", "3", "4"] -) -@pytest.mark.parametrize( - "k", [-3, -2, -1, 0, 1, 2, 3], ids=["-3", "-2", "-1", "0", "1", "2", "3"] -) -@pytest.mark.parametrize( - "n", [1, 2, 3, 4, 5, 6], ids=["1", "2", "3", "4", "5", "6"] -) +@pytest.mark.parametrize("m", [None, 0, 1, 2, 3, 4]) +@pytest.mark.parametrize("k", [-3, -2, -1, 0, 1, 2, 3]) +@pytest.mark.parametrize("n", [1, 2, 3, 4, 5, 6]) def test_tril_indices(n, k, m): result = dpnp.tril_indices(n, k, m) expected = numpy.tril_indices(n, k, m) assert_array_equal(expected, result) -@pytest.mark.parametrize( - "k", [-3, -2, -1, 0, 1, 2, 3], ids=["-3", "-2", "-1", "0", "1", "2", "3"] -) +@pytest.mark.parametrize("k", [-3, -2, -1, 0, 1, 2, 3]) @pytest.mark.parametrize( "array", [ @@ -1102,24 +1136,16 @@ def test_tril_indices_from(array, k): assert_array_equal(expected, result) -@pytest.mark.parametrize( - "m", [None, 0, 1, 2, 3, 4], ids=["None", "0", "1", "2", "3", "4"] -) -@pytest.mark.parametrize( - "k", [-3, -2, -1, 0, 1, 2, 3], ids=["-3", "-2", "-1", "0", "1", "2", "3"] -) -@pytest.mark.parametrize( - "n", [1, 2, 3, 4, 5, 6], ids=["1", "2", "3", "4", "5", "6"] -) +@pytest.mark.parametrize("m", [None, 0, 1, 2, 3, 4]) +@pytest.mark.parametrize("k", [-3, -2, -1, 0, 1, 2, 3]) +@pytest.mark.parametrize("n", [1, 2, 3, 4, 5, 6]) def test_triu_indices(n, k, m): result = dpnp.triu_indices(n, k, m) expected = numpy.triu_indices(n, k, m) assert_array_equal(expected, result) -@pytest.mark.parametrize( - "k", [-3, -2, -1, 0, 1, 2, 3], ids=["-3", "-2", "-1", "0", "1", "2", "3"] -) +@pytest.mark.parametrize("k", [-3, -2, -1, 0, 1, 2, 3]) @pytest.mark.parametrize( "array", [ diff --git a/dpnp/tests/test_linalg.py b/dpnp/tests/test_linalg.py index f239adae84f..851707ee9ca 100644 --- a/dpnp/tests/test_linalg.py +++ b/dpnp/tests/test_linalg.py @@ -2124,9 +2124,7 @@ def test_0D(self, ord, axis): assert_dtype_allclose(result, expected) @pytest.mark.usefixtures("suppress_divide_numpy_warnings") - @pytest.mark.parametrize( - "dtype", get_all_dtypes(xfail_dtypes=[dpnp.uint64]) - ) + @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( "ord", [None, -dpnp.inf, -2, -1, 0, 1, 2, 3.5, dpnp.inf] ) @@ -2141,9 +2139,7 @@ def test_1D(self, dtype, ord, axis, keepdims): assert_dtype_allclose(result, expected) @pytest.mark.usefixtures("suppress_divide_numpy_warnings") - @pytest.mark.parametrize( - "dtype", get_all_dtypes(xfail_dtypes=[dpnp.uint64]) - ) + @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( "ord", [None, -dpnp.inf, -2, -1, 1, 2, 3, dpnp.inf, "fro", "nuc"] ) @@ -2170,9 +2166,7 @@ def test_2D(self, dtype, ord, axis, keepdims): @pytest.mark.usefixtures("suppress_divide_numpy_warnings") @pytest.mark.parametrize( "dtype", - get_all_dtypes( - no_none=True, xfail_dtypes=[dpnp.uint16, dpnp.uint32, dpnp.uint64] - ), + get_all_dtypes(no_none=True), ) @pytest.mark.parametrize( "ord", [None, -dpnp.inf, -2, -1, 1, 2, 3, dpnp.inf, "fro", "nuc"] @@ -2204,10 +2198,7 @@ def test_ND(self, dtype, ord, axis, keepdims): assert_dtype_allclose(result, expected) @pytest.mark.usefixtures("suppress_divide_numpy_warnings") - @pytest.mark.parametrize( - "dtype", - get_all_dtypes(xfail_dtypes=[dpnp.uint16, dpnp.uint32, dpnp.uint64]), - ) + @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( "ord", [None, -dpnp.inf, -2, -1, 1, 2, 3, dpnp.inf, "fro", "nuc"] ) diff --git a/dpnp/tests/test_manipulation.py b/dpnp/tests/test_manipulation.py index 97c951ad156..52c307eaa57 100644 --- a/dpnp/tests/test_manipulation.py +++ b/dpnp/tests/test_manipulation.py @@ -30,7 +30,9 @@ ] testdata += [ ([1, -1, 0], dtype) - for dtype in get_all_dtypes(no_none=True, no_bool=True, no_complex=True) + for dtype in get_all_dtypes( + no_none=True, no_bool=True, no_complex=True, no_unsigned=True + ) ] testdata += [([0.1, 0.0, -0.1], dtype) for dtype in get_float_dtypes()] testdata += [([1j, -1j, 1 - 2j], dtype) for dtype in get_complex_dtypes()] @@ -1719,7 +1721,7 @@ def test_7d_axis_zeros(self, axis): expected = numpy.unique(a, axis=axis) assert_array_equal(result, expected) - @pytest.mark.parametrize("dt", get_integer_dtypes()) + @pytest.mark.parametrize("dt", get_integer_dtypes(no_unsigned=True)) def test_2d_axis_signed_inetger(self, dt): a = numpy.array([[-1], [0]], dtype=dt) ia = dpnp.array(a) diff --git a/dpnp/tests/test_mathematical.py b/dpnp/tests/test_mathematical.py index 756367c4bcb..ee139a77d6a 100644 --- a/dpnp/tests/test_mathematical.py +++ b/dpnp/tests/test_mathematical.py @@ -19,6 +19,7 @@ import dpnp from dpnp.dpnp_array import dpnp_array +from dpnp.dpnp_utils import map_dtype_to_device from .helper import ( assert_dtype_allclose, @@ -64,7 +65,8 @@ def test_angle(self, dtype, deg): expected = numpy.angle(np_a, deg=deg) result = dpnp.angle(dp_a, deg=deg) - assert_dtype_allclose(result, expected) + # For dtype=int8, uint8, NumPy returns float16, but dpnp returns float32 + assert_dtype_allclose(result, expected, check_only_type_kind=True) @pytest.mark.parametrize("dtype", get_complex_dtypes()) @pytest.mark.parametrize("deg", [True, False]) @@ -258,7 +260,8 @@ def test_basic(self, dtype, axis, include_initial): res = dpnp.cumlogsumexp(a, axis=axis, include_initial=include_initial) exp_dt = None - if dtype == dpnp.bool: + dtype_list = [dpnp.bool, dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16] + if dtype in dtype_list: exp_dt = dpnp.default_float_type(a.device) exp = self._get_exp_array(a, axis, exp_dt) @@ -311,7 +314,9 @@ def test_dtype(self, in_dtype, out_dtype): exp = numpy.logaddexp.accumulate(dpnp.asnumpy(a)) exp = exp.astype(out_dtype) - assert_allclose(res, exp, rtol=1e-06) + dtype_list = [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16] + tol = 1e-2 if in_dtype in dtype_list else 1e-6 + assert_allclose(res, exp, rtol=tol) @pytest.mark.usefixtures("suppress_invalid_numpy_warnings") @pytest.mark.parametrize( @@ -391,7 +396,7 @@ def test_usm_ndarray(self, sh, xp_in, xp_out, check): @pytest.mark.parametrize("out_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("dtype", get_all_dtypes()) def test_out_dtype(self, arr_dt, out_dt, dtype): - a = numpy.arange(5, 10).astype(dtype=arr_dt) + a = numpy.arange(1, 6).astype(dtype=arr_dt) out = numpy.zeros_like(a, dtype=out_dt) ia = dpnp.array(a) @@ -495,7 +500,7 @@ def test_usm_ndarray(self, sh, xp_in, xp_out, check): @pytest.mark.parametrize("out_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("dtype", get_all_dtypes()) def test_out_dtype(self, arr_dt, out_dt, dtype): - a = numpy.arange(10, 20).astype(dtype=arr_dt) + a = numpy.arange(5, 15).astype(dtype=arr_dt) out = numpy.zeros_like(a, dtype=out_dt) ia = dpnp.array(a) @@ -869,9 +874,10 @@ class TestFix: "dt", get_all_dtypes(no_none=True, no_complex=True) ) def test_basic(self, dt): - a = numpy.array( - [[1.0, 1.1, 1.5, 1.8], [-1.0, -1.1, -1.5, -1.8]], dtype=dt - ) + x = [[1.0, 1.1, 1.5, 1.8], [-1.0, -1.1, -1.5, -1.8]] + if dpnp.issubdtype(dt, dpnp.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=dt) ia = dpnp.array(a) result = dpnp.fix(ia) @@ -889,15 +895,13 @@ def test_complex(self, xp, dt): "a_dt", get_all_dtypes(no_none=True, no_bool=True, no_complex=True) ) def test_out(self, a_dt): - a = numpy.array( - [[1.0, 1.1, 1.5, 1.8], [-1.0, -1.1, -1.5, -1.8]], dtype=a_dt - ) + x = [[1.0, 1.1, 1.5, 1.8], [-1.0, -1.1, -1.5, -1.8]] + if dpnp.issubdtype(a_dt, dpnp.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=a_dt) ia = dpnp.array(a) - if a.dtype != numpy.float32 and has_support_aspect64(): - out_dt = numpy.float64 - else: - out_dt = numpy.float32 + out_dt = _get_output_data_type(a.dtype) out = numpy.zeros_like(a, dtype=out_dt) iout = dpnp.array(out) @@ -1295,8 +1299,13 @@ def test_basic(self, val, dt): "b_dt", get_all_dtypes(no_none=True, no_complex=True) ) def test_both_input_as_arrays(self, a_dt, b_dt): - a = numpy.array([-1.5, 0, 2.0], dtype=a_dt) - b = numpy.array([-0, 0.5, 1.0], dtype=b_dt) + x = [-1.5, 0, 2.0] + y = [-0, 0.5, 1.0] + if numpy.issubdtype(a_dt, numpy.unsignedinteger): + x = numpy.abs(x) + y = numpy.abs(y) + a = numpy.array(x, dtype=a_dt) + b = numpy.array(y, dtype=b_dt) ia, ib = dpnp.array(a), dpnp.array(b) result = dpnp.heaviside(ia, ib) @@ -1350,7 +1359,9 @@ def test_1d(self, dt): result = dpnp.i0(ia) expected = numpy.i0(a) - assert_dtype_allclose(result, expected) + # numpy promotes result for integer inputs to float64 dtype, but dpnp + # follows Type Promotion Rules + assert_dtype_allclose(result, expected, check_only_type_kind=True) @pytest.mark.parametrize("dt", get_float_dtypes()) def test_2d(self, dt): @@ -1415,9 +1426,20 @@ def test_basic(self, mant_dt, exp_dt): exp = numpy.array(3, dtype=exp_dt) imant, iexp = dpnp.array(mant), dpnp.array(exp) - result = dpnp.ldexp(imant, iexp) - expected = numpy.ldexp(mant, exp) - assert_almost_equal(result, expected) + if dpnp.issubdtype(exp_dt, dpnp.uint64): + assert_raises(ValueError, dpnp.ldexp, imant, iexp) + assert_raises(TypeError, numpy.ldexp, mant, exp) + elif dpnp.issubdtype(exp_dt, dpnp.uint32): + # For this special case, NumPy raises an error on Windows + # because it doesn't have a loop for the input types + # dpnp works fine + result = dpnp.ldexp(imant, iexp) + expected = numpy.ldexp(mant, exp.astype(numpy.int32)) + assert_almost_equal(result, expected) + else: + result = dpnp.ldexp(imant, iexp) + expected = numpy.ldexp(mant, exp) + assert_almost_equal(result, expected) def test_float_scalar(self): a = numpy.array(3) @@ -1893,7 +1915,7 @@ def test_prod_out(self): @pytest.mark.parametrize("out_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("dtype", get_all_dtypes()) def test_prod_out_dtype(self, arr_dt, out_dt, dtype): - a = numpy.arange(10, 20).reshape((2, 5)).astype(dtype=arr_dt) + a = numpy.arange(1, 7).reshape((2, 3)).astype(dtype=arr_dt) out = numpy.zeros_like(a, shape=(2,), dtype=out_dt) ia = dpnp.array(a) @@ -1917,8 +1939,8 @@ def test_prod_Error(self): class TestRationalFunctions: @pytest.mark.parametrize("func", ["gcd", "lcm"]) - @pytest.mark.parametrize("dt1", get_integer_dtypes()) - @pytest.mark.parametrize("dt2", get_integer_dtypes()) + @pytest.mark.parametrize("dt1", get_integer_dtypes(no_unsigned=True)) + @pytest.mark.parametrize("dt2", get_integer_dtypes(no_unsigned=True)) def test_basic(self, func, dt1, dt2): a = numpy.array([12, 120], dtype=dt1) b = numpy.array([20, 120], dtype=dt2) @@ -2013,12 +2035,15 @@ class TestSinc: "dt", get_all_dtypes(no_none=True, no_bool=True, no_float16=False) ) def test_basic(self, dt): + low = 0 if dpnp.issubdtype(dt, dpnp.integer) else -1 a = numpy.linspace(-1, 1, 100, dtype=dt) ia = dpnp.array(a) result = dpnp.sinc(ia) expected = numpy.sinc(a) - assert_dtype_allclose(result, expected) + # numpy promotes result for integer inputs to float64 dtype, but dpnp + # follows Type Promotion Rules similar to other trigonometric functions + assert_dtype_allclose(result, expected, check_only_type_kind=True) def test_bool(self): a = numpy.array([True, False, True]) @@ -2036,7 +2061,9 @@ def test_zero(self, dt): result = dpnp.sinc(ia) expected = numpy.sinc(a) - assert_dtype_allclose(result, expected) + # numpy promotes result for integer inputs to float64 dtype, but dpnp + # follows Type Promotion Rules similar to other trigonometric functions + assert_dtype_allclose(result, expected, check_only_type_kind=True) # TODO: add a proper NumPy version once resolved @testing.with_requires("numpy>=2.0.0") @@ -2151,7 +2178,10 @@ def test_fp16(self): @pytest.mark.parametrize("dt", get_integer_dtypes()) def test_integer(self, dt): - a = numpy.array([1, 0, -3], dtype=dt) + x = [1, 0, -3] + if dpnp.issubdtype(dt, dpnp.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=dt) ia = dpnp.array(a) result = dpnp.spacing(ia) @@ -2308,27 +2338,32 @@ def test_rand(self, dt): assert_dtype_allclose(result, expected) @pytest.mark.parametrize( - "dt", get_all_dtypes(no_none=True, no_bool=True, no_complex=True) + "dt", + get_all_dtypes( + no_none=True, no_bool=True, no_complex=True, no_unsigned=True + ), ) def test_period(self, dt): - a = numpy.array([1, 1 + 256], dtype=dt) + a = numpy.array([1, 1 + 108], dtype=dt) ia = dpnp.array(a) - # unwrap removes jumps greater than 255 - result = dpnp.unwrap(ia, period=255) - expected = numpy.unwrap(a, period=255) + # unwrap removes jumps greater than 107 + result = dpnp.unwrap(ia, period=107) + expected = numpy.unwrap(a, period=107) assert_array_equal(result, expected) @pytest.mark.parametrize( - "dt", get_all_dtypes(no_none=True, no_bool=True, no_complex=True) + "dt", + get_all_dtypes( + no_none=True, no_bool=True, no_complex=True, no_unsigned=True + ), ) def test_rand_period(self, dt): - a = generate_random_numpy_array(10) * 1000 - a = a.astype(dtype=dt) + a = generate_random_numpy_array(10, dt, low=-100, high=100) ia = dpnp.array(a) - result = dpnp.unwrap(ia, period=255) - expected = numpy.unwrap(a, period=255) + result = dpnp.unwrap(ia, period=25) + expected = numpy.unwrap(a, period=25) assert_dtype_allclose(result, expected) def test_simple_seq(self): @@ -2342,19 +2377,21 @@ def test_simple_seq(self): assert_array_equal(result, isimple_seq) @pytest.mark.parametrize( - "dt", get_all_dtypes(no_none=True, no_complex=True) + "dt", + get_all_dtypes( + no_bool=True, no_none=True, no_complex=True, no_unsigned=True + ), ) def test_discont(self, dt): - a = numpy.array([0, 75, 150, 225, 300, 430], dtype=dt) - a = numpy.mod(a, 250) + a = numpy.array([0, 8, 20, 25, 35, 50], dtype=dt) ia = dpnp.array(a) - result = dpnp.unwrap(ia, period=250) - expected = numpy.unwrap(a, period=250) + result = dpnp.unwrap(ia, period=20) + expected = numpy.unwrap(a, period=20) assert_array_equal(result, expected) - result = dpnp.unwrap(ia, period=250, discont=140) - expected = numpy.unwrap(a, period=250, discont=140) + result = dpnp.unwrap(ia, period=20, discont=14) + expected = numpy.unwrap(a, period=20, discont=14) assert_array_equal(result, expected) assert result.dtype == ia.dtype == a.dtype @@ -2469,7 +2506,9 @@ def test_divide_scalar(shape, dtype): [[[1.0, -1.0], [0.1, -0.1]], [-2, -1, 0, 1, 2]], ids=["[[1., -1.], [0.1, -0.1]]", "[-2, -1, 0, 1, 2]"], ) -@pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True)) +@pytest.mark.parametrize( + "dtype", get_all_dtypes(no_bool=True, no_unsigned=True) +) def test_negative(data, dtype): np_a = numpy.array(data, dtype=dtype) dpnp_a = dpnp.array(data, dtype=dtype) @@ -2502,7 +2541,9 @@ def test_negative_boolean(): [[[1.0, -1.0], [0.1, -0.1]], [-2, -1, 0, 1, 2]], ids=["[[1., -1.], [0.1, -0.1]]", "[-2, -1, 0, 1, 2]"], ) -@pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True)) +@pytest.mark.parametrize( + "dtype", get_all_dtypes(no_bool=True, no_unsigned=True) +) def test_positive(data, dtype): np_a = numpy.array(data, dtype=dtype) dpnp_a = dpnp.array(data, dtype=dtype) @@ -2581,7 +2622,9 @@ def test_float_remainder_fmod_nans_inf(func, dtype, lhs, rhs): [[2, 0, -2], [1.1, -1.1]], ids=["[2, 0, -2]", "[1.1, -1.1]"], ) -@pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True)) +@pytest.mark.parametrize( + "dtype", get_all_dtypes(no_bool=True, no_unsigned=True) +) def test_sign(data, dtype): np_a = numpy.array(data, dtype=dtype) dpnp_a = dpnp.array(data, dtype=dtype) @@ -2610,7 +2653,9 @@ def test_sign_boolean(): [[2, 0, -2], [1.1, -1.1]], ids=["[2, 0, -2]", "[1.1, -1.1]"], ) -@pytest.mark.parametrize("dtype", get_all_dtypes(no_complex=True)) +@pytest.mark.parametrize( + "dtype", get_all_dtypes(no_complex=True, no_unsigned=True) +) def test_signbit(data, dtype): np_a = numpy.array(data, dtype=dtype) dpnp_a = dpnp.array(data, dtype=dtype) @@ -2822,7 +2867,10 @@ def test_divide(self, dtype): dp_array1 = dpnp.array(np_array1) dp_array2 = dpnp.array(np_array2) - out_dtype = _get_output_data_type(dtype) + if numpy.issubdtype(dtype, numpy.integer): + out_dtype = map_dtype_to_device(dpnp.float64, dp_array1.sycl_device) + else: + out_dtype = _get_output_data_type(dtype) dp_out = dpnp.empty(expected.shape, dtype=out_dtype) result = dpnp.divide(dp_array1, dp_array2, out=dp_out) @@ -3152,11 +3200,14 @@ class TestLogSumExp: def test_logsumexp(self, dtype, axis, keepdims): a = dpnp.ones((3, 4, 5, 6, 7), dtype=dtype) res = dpnp.logsumexp(a, axis=axis, keepdims=keepdims) - exp_dtype = ( - dpnp.default_float_type(a.device) if dtype == dpnp.bool else None - ) + + exp_dt = None + dtype_list = [dpnp.bool, dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16] + if dtype in dtype_list: + exp_dt = dpnp.default_float_type(a.device) + exp = numpy.logaddexp.reduce( - dpnp.asnumpy(a), axis=axis, keepdims=keepdims, dtype=exp_dtype + dpnp.asnumpy(a), axis=axis, keepdims=keepdims, dtype=exp_dt ) assert_dtype_allclose(res, exp) @@ -3166,17 +3217,18 @@ def test_logsumexp(self, dtype, axis, keepdims): @pytest.mark.parametrize("keepdims", [True, False]) def test_logsumexp_out(self, dtype, axis, keepdims): a = dpnp.ones((3, 4, 5, 6, 7), dtype=dtype) - exp_dtype = ( - dpnp.default_float_type(a.device) if dtype == dpnp.bool else None - ) + exp_dt = None + dtype_list = [dpnp.bool, dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16] + if dtype in dtype_list: + exp_dt = dpnp.default_float_type(a.device) exp = numpy.logaddexp.reduce( - dpnp.asnumpy(a), axis=axis, keepdims=keepdims, dtype=exp_dtype + dpnp.asnumpy(a), axis=axis, keepdims=keepdims, dtype=exp_dt ) - exp_dtype = exp.dtype - if exp_dtype == numpy.float64 and not has_support_aspect64(): - exp_dtype = numpy.float32 - dpnp_out = dpnp.empty_like(a, shape=exp.shape, dtype=exp_dtype) + exp_dt = exp.dtype + if exp_dt == numpy.float64 and not has_support_aspect64(): + exp_dt = numpy.float32 + dpnp_out = dpnp.empty_like(a, shape=exp.shape, dtype=exp_dt) res = dpnp.logsumexp(a, axis=axis, out=dpnp_out, keepdims=keepdims) assert res is dpnp_out @@ -3192,7 +3244,9 @@ def test_logsumexp_dtype(self, in_dtype, out_dtype): exp = numpy.logaddexp.reduce(dpnp.asnumpy(a)) exp = exp.astype(out_dtype) - assert_allclose(res, exp, rtol=1e-06) + dtype_list = [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16] + tol = 1e-2 if in_dtype in dtype_list else 1e-6 + assert_allclose(res, exp, rtol=tol) @testing.with_requires("numpy>=1.26.4") @pytest.mark.usefixtures("suppress_invalid_numpy_warnings") @@ -3204,15 +3258,23 @@ def test_logsumexp_dtype(self, in_dtype, out_dtype): ) @pytest.mark.parametrize("dtype", get_all_dtypes()) def test_logsumexp_out_dtype(self, arr_dt, out_dt, dtype): - a = numpy.arange(10, 20).reshape((2, 5)).astype(dtype=arr_dt) + a = numpy.arange(1, 11).reshape((2, 5)).astype(dtype=arr_dt) out = numpy.zeros_like(a, shape=(2,), dtype=out_dt) ia = dpnp.array(a) iout = dpnp.array(out) result = dpnp.logsumexp(ia, out=iout, dtype=dtype, axis=1) - exp = numpy.logaddexp.reduce(a, out=out, axis=1) - assert_allclose(result, exp.astype(dtype), rtol=1e-06) + if numpy.issubdtype(out_dt, numpy.uint64): + # NumPy returns incorrect results for this case if out kwarg is used + exp = numpy.logaddexp.reduce(a, axis=1) + exp = exp.astype(out_dt) + else: + exp = numpy.logaddexp.reduce(a, out=out, axis=1) + + dtype_list = [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16] + tol = 1e-2 if arr_dt in dtype_list else 1e-6 + assert_allclose(result, exp.astype(dtype), rtol=tol) assert result is iout @@ -3223,11 +3285,14 @@ class TestReduceHypot: def test_reduce_hypot(self, dtype, axis, keepdims): a = dpnp.ones((3, 4, 5, 6, 7), dtype=dtype) res = dpnp.reduce_hypot(a, axis=axis, keepdims=keepdims) - exp_dtype = ( - dpnp.default_float_type(a.device) if dtype == dpnp.bool else None - ) + + exp_dt = None + dtype_list = [dpnp.bool, dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16] + if dtype in dtype_list: + exp_dt = dpnp.default_float_type(a.device) + exp = numpy.hypot.reduce( - dpnp.asnumpy(a), axis=axis, keepdims=keepdims, dtype=exp_dtype + dpnp.asnumpy(a), axis=axis, keepdims=keepdims, dtype=exp_dt ) assert_dtype_allclose(res, exp) @@ -3237,17 +3302,18 @@ def test_reduce_hypot(self, dtype, axis, keepdims): @pytest.mark.parametrize("keepdims", [True, False]) def test_reduce_hypot_out(self, dtype, axis, keepdims): a = dpnp.ones((3, 4, 5, 6, 7), dtype=dtype) - exp_dtype = ( - dpnp.default_float_type(a.device) if dtype == dpnp.bool else None - ) + exp_dt = None + dtype_list = [dpnp.bool, dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16] + if dtype in dtype_list: + exp_dt = dpnp.default_float_type(a.device) exp = numpy.hypot.reduce( - dpnp.asnumpy(a), axis=axis, keepdims=keepdims, dtype=exp_dtype + dpnp.asnumpy(a), axis=axis, keepdims=keepdims, dtype=exp_dt ) - exp_dtype = exp.dtype - if exp_dtype == numpy.float64 and not has_support_aspect64(): - exp_dtype = numpy.float32 - dpnp_out = dpnp.empty_like(a, shape=exp.shape, dtype=exp_dtype) + exp_dt = exp.dtype + if exp_dt == numpy.float64 and not has_support_aspect64(): + exp_dt = numpy.float32 + dpnp_out = dpnp.empty_like(a, shape=exp.shape, dtype=exp_dt) res = dpnp.reduce_hypot(a, axis=axis, out=dpnp_out, keepdims=keepdims) assert res is dpnp_out @@ -3263,7 +3329,9 @@ def test_reduce_hypot_dtype(self, in_dtype, out_dtype): exp = numpy.hypot.reduce(dpnp.asnumpy(a)) exp = exp.astype(out_dtype) - assert_allclose(res, exp, rtol=1e-06) + dtype_list = [dpnp.int8, dpnp.uint8] + tol = 1e-2 if in_dtype in dtype_list else 1e-6 + assert_allclose(res, exp, rtol=tol) @pytest.mark.parametrize( "arr_dt", get_all_dtypes(no_none=True, no_complex=True) @@ -3348,7 +3416,7 @@ def test_invalid_out(self, out): class TestPower: @pytest.mark.parametrize("val_type", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("data_type", get_all_dtypes()) - @pytest.mark.parametrize("val", [1.5, 1, 5], ids=["1.5", "1", "5"]) + @pytest.mark.parametrize("val", [1.5, 1, 3], ids=["1.5", "1", "3"]) @pytest.mark.parametrize( "array", [ @@ -3690,8 +3758,8 @@ def test_matmul_bool(self, shape1, shape2): ], ) def test_matmul_axes_ND_ND(self, dtype, axes): - a = generate_random_numpy_array((2, 5, 3, 4), dtype) - b = generate_random_numpy_array((4, 2, 5, 3), dtype) + a = generate_random_numpy_array((2, 5, 3, 4), dtype, low=-5, high=5) + b = generate_random_numpy_array((4, 2, 5, 3), dtype, low=-5, high=5) ia = dpnp.array(a) ib = dpnp.array(b) @@ -3759,8 +3827,8 @@ def test_matmul_axes_1D_1D(self): ], ) def test_matmul_axes_out(self, dtype, axes, out_shape): - a = generate_random_numpy_array((2, 5, 3, 4), dtype) - b = generate_random_numpy_array((4, 2, 5, 3), dtype) + a = generate_random_numpy_array((2, 5, 3, 4), dtype, low=-5, high=5) + b = generate_random_numpy_array((4, 2, 5, 3), dtype, low=-5, high=5) ia = dpnp.array(a) ib = dpnp.array(b) @@ -3811,8 +3879,8 @@ def test_matmul_axes_out_1D(self, axes, b_shape, out_shape): ], ) def test_matmul_dtype_matrix_inout(self, in_dt, out_dt, shape1, shape2): - a1 = generate_random_numpy_array(shape1, in_dt) - a2 = generate_random_numpy_array(shape2, in_dt) + a1 = generate_random_numpy_array(shape1, in_dt, low=-5, high=5) + a2 = generate_random_numpy_array(shape2, in_dt, low=-5, high=5) b1 = dpnp.asarray(a1) b2 = dpnp.asarray(a2) @@ -3840,8 +3908,8 @@ def test_matmul_dtype_matrix_inout(self, in_dt, out_dt, shape1, shape2): ], ) def test_matmul_dtype_matrix_inputs(self, dtype1, dtype2, shape1, shape2): - a1 = generate_random_numpy_array(shape1, dtype1) - a2 = generate_random_numpy_array(shape2, dtype2) + a1 = generate_random_numpy_array(shape1, dtype1, low=-5, high=5) + a2 = generate_random_numpy_array(shape2, dtype2, low=-5, high=5) b1 = dpnp.asarray(a1) b2 = dpnp.asarray(a2) @@ -4054,9 +4122,10 @@ def test_matmul_strided_vec_mat(self, shape, incx, incy, transpose): ) def test_matmul_out1(self, order1, order2, out_order, dtype): # test gemm with out keyword - a1 = numpy.arange(20, dtype=dtype).reshape(5, 4, order=order1) - a2 = numpy.arange(28, dtype=dtype).reshape(4, 7, order=order2) - + a1 = generate_random_numpy_array((5, 4), dtype, low=-5, high=5) + a2 = generate_random_numpy_array((4, 7), dtype, low=-5, high=5) + a1 = numpy.array(a1, order=order1) + a2 = numpy.array(a2, order=order2) b1 = dpnp.asarray(a1) b2 = dpnp.asarray(a2) @@ -4078,8 +4147,8 @@ def test_matmul_out2(self, trans, dtype): # test gemm_batch with out keyword # the base of input arrays is c-contiguous # the base of output array is c-contiguous or f-contiguous - a1 = numpy.arange(24, dtype=dtype).reshape(2, 3, 4) - a2 = numpy.arange(40, dtype=dtype).reshape(2, 4, 5) + a1 = generate_random_numpy_array((2, 3, 4), dtype, low=-5, high=5) + a2 = generate_random_numpy_array((2, 4, 5), dtype, low=-5, high=5) b1 = dpnp.asarray(a1) b2 = dpnp.asarray(a2) @@ -4106,8 +4175,8 @@ def test_matmul_out3(self, trans, dtype): # test gemm_batch with out keyword # the base of input arrays is f-contiguous # the base of output array is c-contiguous or f-contiguous - a1 = numpy.arange(24, dtype=dtype).reshape(2, 4, 3) - a2 = numpy.arange(40, dtype=dtype).reshape(2, 5, 4) + a1 = generate_random_numpy_array((2, 4, 3), dtype, low=-5, high=5) + a2 = generate_random_numpy_array((2, 5, 4), dtype, low=-5, high=5) b1 = dpnp.asarray(a1) b2 = dpnp.asarray(a2) diff --git a/dpnp/tests/test_nanfunctions.py b/dpnp/tests/test_nanfunctions.py index 5645586219e..9d516cb6fba 100644 --- a/dpnp/tests/test_nanfunctions.py +++ b/dpnp/tests/test_nanfunctions.py @@ -586,7 +586,7 @@ def test_nanprod_out(self): @pytest.mark.parametrize("out_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("dtype", get_all_dtypes()) def test_nanprod_out_dtype(self, arr_dt, out_dt, dtype): - a = numpy.arange(10, 20).reshape((2, 5)).astype(dtype=arr_dt) + a = numpy.arange(1, 7).reshape((2, 3)).astype(dtype=arr_dt) out = numpy.zeros_like(a, shape=(2,), dtype=out_dt) ia = dpnp.array(a) diff --git a/dpnp/tests/test_ndarray.py b/dpnp/tests/test_ndarray.py index 153b3d0c2e9..1ceaebd5dbc 100644 --- a/dpnp/tests/test_ndarray.py +++ b/dpnp/tests/test_ndarray.py @@ -23,6 +23,8 @@ ids=["[-2, -1, 0, 1, 2]", "[[-2, -1], [1, 2]]", "[]"], ) def test_astype(arr, arr_dtype, res_dtype): + if numpy.issubdtype(arr_dtype, numpy.unsignedinteger): + arr = numpy.abs(arr) numpy_array = numpy.array(arr, dtype=arr_dtype) dpnp_array = dpnp.array(numpy_array) expected = numpy_array.astype(res_dtype) @@ -43,6 +45,8 @@ def test_astype_subok_error(): ids=["[-2, -1, 0, 1, 2]", "[[-2, -1], [1, 2]]", "[]"], ) def test_flatten(arr, arr_dtype): + if numpy.issubdtype(arr_dtype, numpy.unsignedinteger): + arr = numpy.abs(arr) numpy_array = numpy.array(arr, dtype=arr_dtype) dpnp_array = dpnp.array(arr, dtype=arr_dtype) expected = numpy_array.flatten() diff --git a/dpnp/tests/test_outer.py b/dpnp/tests/test_outer.py index 77f57ebf7dd..bcdc8091ed0 100644 --- a/dpnp/tests/test_outer.py +++ b/dpnp/tests/test_outer.py @@ -59,14 +59,14 @@ class TestScalarOuter(unittest.TestCase): @testing.numpy_cupy_allclose(type_check=False) def test_first_is_scalar(self, xp, dtype): scalar = 4 - a = xp.arange(5**3, dtype=dtype).reshape(5, 5, 5) + a = xp.arange(24, dtype=dtype).reshape(2, 3, 4) return xp.outer(scalar, a) @testing.for_all_dtypes() @testing.numpy_cupy_allclose(type_check=False) def test_second_is_scalar(self, xp, dtype): - scalar = 7 - a = xp.arange(5**3, dtype=dtype).reshape(5, 5, 5) + scalar = 5 + a = xp.arange(24, dtype=dtype).reshape(2, 3, 4) return xp.outer(a, scalar) diff --git a/dpnp/tests/test_product.py b/dpnp/tests/test_product.py index 95c643a6494..b9b199b0d28 100644 --- a/dpnp/tests/test_product.py +++ b/dpnp/tests/test_product.py @@ -5,6 +5,7 @@ from numpy.testing import assert_raises import dpnp +from dpnp.dpnp_utils import map_dtype_to_device from .helper import ( assert_dtype_allclose, @@ -15,18 +16,6 @@ from .third_party.cupy import testing -def _assert_selective_dtype_allclose(result, expected, dtype): - # For numpy.dot, numpy.vdot, numpy.kron, numpy.inner, and numpy.tensordot, - # when inputs are an scalar (which has the default dtype of platform) and - # an array, the scalar dtype precision determines the output dtype - # precision. In dpnp, we rely on dpnp.multiply for scalar-array product - # and array (not scalar) determines output dtype precision of dpnp.multiply - if dtype in [numpy.int32, numpy.float32, numpy.complex64]: - assert_dtype_allclose(result, expected, check_only_type_kind=True) - else: - assert_dtype_allclose(result, expected) - - class TestCross: def setup_method(self): numpy.random.seed(42) @@ -221,11 +210,11 @@ def test_scalar(self, dtype): result = dpnp.dot(a, ib) expected = numpy.dot(a, b) - _assert_selective_dtype_allclose(result, expected, dtype) + assert_dtype_allclose(result, expected) result = dpnp.dot(ib, a) expected = numpy.dot(b, a) - _assert_selective_dtype_allclose(result, expected, dtype) + assert_dtype_allclose(result, expected) @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( @@ -256,8 +245,8 @@ def test_scalar(self, dtype): ], ) def test_basic(self, dtype, shape1, shape2): - a = generate_random_numpy_array(shape1, dtype) - b = generate_random_numpy_array(shape2, dtype) + a = generate_random_numpy_array(shape1, dtype, low=-5, high=5) + b = generate_random_numpy_array(shape2, dtype, low=-5, high=5) ia = dpnp.array(a) ib = dpnp.array(b) @@ -288,12 +277,15 @@ def test_out_scalar(self, dtype): b = generate_random_numpy_array(10, dtype) ib = dpnp.array(b) - dp_out = dpnp.empty(10, dtype=dtype) + np_res_dtype = numpy.result_type(type(a), b) + out = numpy.empty(10, dtype=np_res_dtype) + dp_res_dtype = map_dtype_to_device(np_res_dtype, ib.sycl_device) + dp_out = dpnp.array(out, dtype=dp_res_dtype) result = dpnp.dot(a, ib, out=dp_out) - expected = numpy.dot(a, b) + expected = numpy.dot(a, b, out=out) assert result is dp_out - _assert_selective_dtype_allclose(result, expected, dtype) + assert_dtype_allclose(result, expected) @pytest.mark.parametrize("dtype", get_all_dtypes()) @pytest.mark.parametrize( @@ -324,8 +316,8 @@ def test_out_scalar(self, dtype): ], ) def test_out(self, dtype, shape1, shape2, out_shape): - a = generate_random_numpy_array(shape1, dtype) - b = generate_random_numpy_array(shape2, dtype) + a = generate_random_numpy_array(shape1, dtype, low=-5, high=5) + b = generate_random_numpy_array(shape2, dtype, low=-5, high=5) ia = dpnp.array(a) ib = dpnp.array(b) @@ -376,7 +368,9 @@ def test_out_error_scalar(self, ia): # output data type is incorrect dp_out = dpnp.empty((10,), dtype=dpnp.complex64) out = numpy.empty((10,), dtype=numpy.complex64) - assert_raises(ValueError, dpnp.dot, ia, ib, out=dp_out) + # For scalar dpnp raises TypeError, and for empty array raises ValueError + # NumPy raises ValueError for both cases + assert_raises((TypeError, ValueError), dpnp.dot, ia, ib, out=dp_out) assert_raises(ValueError, numpy.dot, a, b, out=out) # output shape is incorrect @@ -442,11 +436,11 @@ def test_scalar(self, dtype): result = dpnp.inner(a, ib) expected = numpy.inner(a, b) - _assert_selective_dtype_allclose(result, expected, dtype) + assert_dtype_allclose(result, expected) result = dpnp.inner(ib, a) expected = numpy.inner(b, a) - _assert_selective_dtype_allclose(result, expected, dtype) + assert_dtype_allclose(result, expected) @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( @@ -460,8 +454,8 @@ def test_scalar(self, dtype): ], ) def test_basic(self, dtype, shape1, shape2): - a = generate_random_numpy_array(shape1, dtype) - b = generate_random_numpy_array(shape2, dtype) + a = generate_random_numpy_array(shape1, dtype, low=-5, high=5) + b = generate_random_numpy_array(shape2, dtype, low=-5, high=5) ia = dpnp.array(a) ib = dpnp.array(b) @@ -510,11 +504,12 @@ def test_scalar(self, dtype): result = dpnp.kron(a, ib) expected = numpy.kron(a, b) - _assert_selective_dtype_allclose(result, expected, dtype) + assert_dtype_allclose(result, expected) result = dpnp.kron(ib, a) expected = numpy.kron(b, a) - _assert_selective_dtype_allclose(result, expected, dtype) + # NumPy returns incorrect dtype on Windows, add check_type=False + assert_dtype_allclose(result, expected, check_type=False) @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( @@ -611,7 +606,7 @@ def setup_method(self): ((6,), (6, 10), (10, 7), (7, 8)), ((4, 6), (6, 10), (10, 7), (7,)), ((6,), (6, 10), (10, 7), (7,)), - ((4, 6), (6, 9), (9, 7), (7, 8), (8, 3)), + ((4, 6), (6, 2), (2, 7), (7, 5), (5, 3)), ], ids=[ "two_arrays", @@ -631,7 +626,7 @@ def test_basic(self, shapes, dtype): numpy_array_list = [] dpnp_array_list = [] for shape in shapes: - a = generate_random_numpy_array(shape, dtype) + a = generate_random_numpy_array(shape, dtype, low=-2, high=2) ia = dpnp.array(a) numpy_array_list.append(a) @@ -655,7 +650,7 @@ def test_basic(self, shapes, dtype): ((6,), (6, 10), (10, 7), (7, 8), (8,)), ((4, 6), (6, 10), (10, 7), (7,), (4,)), ((6,), (6, 10), (10, 7), (7,), ()), - ((4, 6), (6, 9), (9, 7), (7, 8), (8, 3), (4, 3)), + ((4, 6), (6, 2), (2, 7), (7, 5), (5, 3), (4, 3)), ], ids=[ "two_arrays", @@ -675,7 +670,7 @@ def test_out(self, shapes, dtype): numpy_array_list = [] dpnp_array_list = [] for shape in shapes[:-1]: - a = generate_random_numpy_array(shape, dtype) + a = generate_random_numpy_array(shape, dtype, low=-2, high=2) ia = dpnp.array(a) numpy_array_list.append(a) @@ -762,17 +757,17 @@ def test_scalar(self, dtype): result = dpnp.tensordot(a, ib, axes=0) expected = numpy.tensordot(a, b, axes=0) - _assert_selective_dtype_allclose(result, expected, dtype) + assert_dtype_allclose(result, expected) result = dpnp.tensordot(ib, a, axes=0) expected = numpy.tensordot(b, a, axes=0) - _assert_selective_dtype_allclose(result, expected, dtype) + assert_dtype_allclose(result, expected) @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("axes", [0, 1, 2]) def test_basic(self, dtype, axes): - a = generate_random_numpy_array((4, 4, 4), dtype) - b = generate_random_numpy_array((4, 4, 4), dtype) + a = generate_random_numpy_array((4, 4, 4), dtype, low=-5, high=5) + b = generate_random_numpy_array((4, 4, 4), dtype, low=-5, high=5) ia = dpnp.array(a) ib = dpnp.array(b) @@ -792,8 +787,8 @@ def test_basic(self, dtype, axes): ], ) def test_axes(self, dtype, axes): - a = generate_random_numpy_array((2, 5, 3, 4), dtype) - b = generate_random_numpy_array((4, 2, 5, 3), dtype) + a = generate_random_numpy_array((2, 5, 3, 4), dtype, low=-5, high=5) + b = generate_random_numpy_array((4, 2, 5, 3), dtype, low=-5, high=5) ia = dpnp.array(a) ib = dpnp.array(b) @@ -804,8 +799,8 @@ def test_axes(self, dtype, axes): @pytest.mark.parametrize("dtype1", get_all_dtypes()) @pytest.mark.parametrize("dtype2", get_all_dtypes()) def test_input_dtype_matrix(self, dtype1, dtype2): - a = generate_random_numpy_array((3, 4, 5), dtype1) - b = generate_random_numpy_array((4, 5, 2), dtype2) + a = generate_random_numpy_array((3, 4, 5), dtype1, low=-5, high=5) + b = generate_random_numpy_array((4, 5, 2), dtype2, low=-5, high=5) ia = dpnp.array(a) ib = dpnp.array(b) @@ -896,11 +891,11 @@ def test_scalar(self, dtype): result = dpnp.vdot(ia, b) expected = numpy.vdot(a, b) - _assert_selective_dtype_allclose(result, expected, dtype) + assert_dtype_allclose(result, expected) result = dpnp.vdot(b, ia) expected = numpy.vdot(b, a) - _assert_selective_dtype_allclose(result, expected, dtype) + assert_dtype_allclose(result, expected) @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( diff --git a/dpnp/tests/test_sort.py b/dpnp/tests/test_sort.py index 0a4fdfec528..665ab8bee45 100644 --- a/dpnp/tests/test_sort.py +++ b/dpnp/tests/test_sort.py @@ -369,8 +369,13 @@ def test_complex(self, dtype): assert result.dtype == expected.dtype -@pytest.mark.parametrize("kth", [0, 1], ids=["0", "1"]) -@pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) +@pytest.mark.parametrize("kth", [0, 1]) +@pytest.mark.parametrize( + "dtype", + get_all_dtypes( + no_none=True, no_unsigned=True, xfail_dtypes=[dpnp.int8, dpnp.int16] + ), +) @pytest.mark.parametrize( "array", [ diff --git a/dpnp/tests/test_strides.py b/dpnp/tests/test_strides.py index 0f6732ab9a4..f9cb3d52018 100644 --- a/dpnp/tests/test_strides.py +++ b/dpnp/tests/test_strides.py @@ -161,7 +161,15 @@ def test_logsumexp(dtype): result = dpnp.logsumexp(dpa) expected = numpy.logaddexp.reduce(a) - assert_allclose(result, expected) + # for int8, uint8, NumPy returns float16 but dpnp returns float64 + # for int16, uint16, NumPy returns float32 but dpnp returns float64 + if dtype in [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16]: + check_only_type_kind = True + else: + check_only_type_kind = False + assert_dtype_allclose( + result, expected, check_only_type_kind=check_only_type_kind + ) @pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True, no_complex=True)) @@ -171,7 +179,15 @@ def test_cumlogsumexp(dtype): result = dpnp.cumlogsumexp(dpa) expected = numpy.logaddexp.accumulate(a) - assert_allclose(result, expected) + # for int8, uint8, NumPy returns float16 but dpnp returns float64 + # for int16, uint16, NumPy returns float32 but dpnp returns float64 + if dtype in [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16]: + check_only_type_kind = True + else: + check_only_type_kind = False + assert_dtype_allclose( + result, expected, check_only_type_kind=check_only_type_kind + ) @pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True, no_complex=True)) @@ -181,15 +197,29 @@ def test_reduce_hypot(dtype): result = dpnp.reduce_hypot(dpa) expected = numpy.hypot.reduce(a) - assert_allclose(result, expected) + # for int8, uint8, NumPy returns float16 but dpnp returns float64 + # for int16, uint16, NumPy returns float32 but dpnp returns float64 + if dtype in [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16]: + check_only_type_kind = True + else: + check_only_type_kind = False + assert_dtype_allclose( + result, expected, check_only_type_kind=check_only_type_kind + ) -@pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True, no_complex=True)) -@pytest.mark.parametrize("shape", [(10,)], ids=["(10,)"]) -def test_strides_erf(dtype, shape): - a = dpnp.reshape( - dpnp.linspace(-1, 1, num=numpy.prod(shape), dtype=dtype), shape - ) +@pytest.mark.parametrize( + "dtype", + get_all_dtypes( + no_none=True, + no_bool=True, + no_complex=True, + no_unsigned=True, + xfail_dtypes=[dpnp.int8, dpnp.int16], + ), +) +def test_strides_erf(dtype): + a = dpnp.linspace(-1, 1, num=10, dtype=dtype) b = a[::2] result = dpnp.erf(b) diff --git a/dpnp/tests/test_sum.py b/dpnp/tests/test_sum.py index 21ecab42a6a..e63c3a768ea 100644 --- a/dpnp/tests/test_sum.py +++ b/dpnp/tests/test_sum.py @@ -2,14 +2,13 @@ import numpy import pytest -from numpy.testing import ( - assert_array_equal, -) +from numpy.testing import assert_array_equal import dpnp from .helper import ( assert_dtype_allclose, + generate_random_numpy_array, get_all_dtypes, get_float_dtypes, ) @@ -32,14 +31,14 @@ (40, 35), ], ) -@pytest.mark.parametrize("dtype_in", get_all_dtypes()) +@pytest.mark.parametrize("dtype_in", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("dtype_out", get_all_dtypes()) @pytest.mark.parametrize("transpose", [True, False]) @pytest.mark.parametrize("keepdims", [True, False]) @pytest.mark.parametrize("order", ["C", "F"]) def test_sum(shape, dtype_in, dtype_out, transpose, keepdims, order): - size = numpy.prod(shape) - a_np = numpy.arange(size).astype(dtype_in).reshape(shape, order=order) + a_np = generate_random_numpy_array(shape, dtype_in) + a_np = numpy.array(a_np, order=order) a = dpnp.asarray(a_np) if transpose: @@ -53,9 +52,16 @@ def test_sum(shape, dtype_in, dtype_out, transpose, keepdims, order): axes.append(tuple(axes_range)) for axis in axes: - numpy_res = a_np.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) + if numpy.issubdtype(dtype_out, numpy.bool_): + # If summation is zero and dtype=numpy.bool is passed to numpy.sum + # NumPy returns True which is not correct + numpy_res = a_np.sum(axis=axis, keepdims=keepdims).astype( + numpy.bool_ + ) + else: + numpy_res = a_np.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) dpnp_res = a.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) - assert_array_equal(numpy_res, dpnp_res.asnumpy()) + assert_dtype_allclose(dpnp_res, numpy_res, factor=16) @pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True)) diff --git a/dpnp/tests/test_umath.py b/dpnp/tests/test_umath.py index 65b7908b09f..01cc3f12297 100644 --- a/dpnp/tests/test_umath.py +++ b/dpnp/tests/test_umath.py @@ -180,8 +180,16 @@ def _get_numpy_arrays_2in_1out(func_name, dtype, range): def _get_output_data_type(dtype): """Return a data type specified by input `dtype` and device capabilities.""" - if dpnp.issubdtype(dtype, dpnp.bool): + dtype_float16 = any( + dpnp.issubdtype(dtype, t) for t in (dpnp.bool, dpnp.int8, dpnp.uint8) + ) + dtype_float32 = any( + dpnp.issubdtype(dtype, t) for t in (dpnp.int16, dpnp.uint16) + ) + if dtype_float16: out_dtype = dpnp.float16 if has_support_aspect16() else dpnp.float32 + elif dtype_float32: + out_dtype = dpnp.float32 elif dpnp.issubdtype(dtype, dpnp.complexfloating): out_dtype = dpnp.complex64 if has_support_aspect64() and dtype != dpnp.complex64: @@ -317,7 +325,10 @@ class TestDegrees: "dtype", get_all_dtypes(no_none=True, no_complex=True) ) def test_basic(self, dtype): - a = numpy.array([numpy.pi, -0.5 * numpy.pi], dtype=dtype) + x = [numpy.pi, -0.5 * numpy.pi] + if numpy.issubdtype(dtype, numpy.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=dtype) ia = dpnp.array(a) result = dpnp.degrees(ia) @@ -356,7 +367,9 @@ def test_type_conversion(self, dt1, dt2): assert_dtype_allclose(result, expected, check_only_type_kind=True) @pytest.mark.usefixtures("suppress_invalid_numpy_warnings") - @pytest.mark.parametrize("dt", get_all_dtypes(no_none=True)) + @pytest.mark.parametrize( + "dt", get_all_dtypes(no_none=True, no_unsigned=True) + ) def test_negative_base_value(self, dt): a = numpy.array([-1, -4], dtype=dt) ia = dpnp.array(a) @@ -365,7 +378,9 @@ def test_negative_base_value(self, dt): expected = numpy.float_power(a, 1.5) assert_allclose(result, expected) - @pytest.mark.parametrize("dt", get_all_dtypes(no_none=True)) + @pytest.mark.parametrize( + "dt", get_all_dtypes(no_none=True, no_unsigned=True) + ) def test_negative_base_value_complex_dtype(self, dt): a = numpy.array([-1, -4], dtype=dt) ia = dpnp.array(a) @@ -460,7 +475,8 @@ def test_values(self, dt): assert_dtype_allclose(result, expected) @pytest.mark.parametrize( - "dt", get_all_dtypes(no_none=True, no_complex=True) + "dt", + [numpy.bool_, numpy.int32, numpy.int64, numpy.float32, numpy.float64], ) def test_range(self, dt): a = numpy.array([1000000, -1000000, 1000200, -1000200], dtype=dt) @@ -508,7 +524,10 @@ class TestRadians: "dtype", get_all_dtypes(no_none=True, no_complex=True) ) def test_basic(self, dtype): - a = numpy.array([180.0, -90.0], dtype=dtype) + x = [120.0, -90.0] + if numpy.issubdtype(dtype, numpy.unsignedinteger): + x = numpy.abs(x) + a = numpy.array(x, dtype=dtype) ia = dpnp.array(a) result = dpnp.radians(ia) @@ -712,6 +731,7 @@ class TestUmath: def func_params(self, request): return request.param + @pytest.mark.filterwarnings("ignore:overflow encountered:RuntimeWarning") @pytest.mark.usefixtures("suppress_divide_invalid_numpy_warnings") @pytest.mark.parametrize("dtype", get_all_dtypes()) def test_out(self, func_params, dtype): diff --git a/dpnp/tests/third_party/cupy/testing/_loops.py b/dpnp/tests/third_party/cupy/testing/_loops.py index e9a0fde7104..603ec22b1a2 100644 --- a/dpnp/tests/third_party/cupy/testing/_loops.py +++ b/dpnp/tests/third_party/cupy/testing/_loops.py @@ -1082,30 +1082,17 @@ def _get_int_bool_dtypes(): _complex_dtypes = _get_supported_complex_dtypes() _regular_float_dtypes = _get_supported_float_dtypes() -_float_dtypes = _get_float_dtypes() -_signed_dtypes = _get_signed_dtypes() -_unsigned_dtypes = _get_unsigned_dtypes() -_int_dtypes = _get_int_dtypes() -_int_bool_dtypes = _get_int_bool_dtypes() +_float_dtypes = _regular_float_dtypes +_signed_dtypes = () +_unsigned_dtypes = tuple(numpy.dtype(i).type for i in "BHILQ") +_int_dtypes = _signed_dtypes + _unsigned_dtypes +_int_bool_dtypes = _int_dtypes _regular_dtypes = _regular_float_dtypes + _int_bool_dtypes _dtypes = _float_dtypes + _int_bool_dtypes def _make_all_dtypes(no_float16, no_bool, no_complex): - if no_float16: - dtypes = _regular_float_dtypes - else: - dtypes = _float_dtypes - - if no_bool: - dtypes += _int_dtypes - else: - dtypes += _int_bool_dtypes - - if config.complex_types and not no_complex: - dtypes += _complex_dtypes - - return dtypes + return (numpy.int64, numpy.int32) + _get_supported_float_dtypes() def for_all_dtypes( From fc64fa4af7d707ed6f35f391af72874549e79dfa Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Mon, 16 Dec 2024 19:41:01 -0800 Subject: [PATCH 04/13] run linux tests in serial --- .github/workflows/conda-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 1afca13378d..d4754ff151c 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -274,7 +274,7 @@ jobs: env: DPNP_TEST_ALL_INT_TYPES: 1 run: | - pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests test_windows: name: Test ['windows-2019', python='${{ matrix.python }}'] From 5c46710de2c459e1637e4c51244a1916a27b3f40 Mon Sep 17 00:00:00 2001 From: vlad-perevezentsev Date: Tue, 17 Dec 2024 13:31:31 +0100 Subject: [PATCH 05/13] Add `order` agrument to `generate_random_numpy_array()` (#2237) This PR suggests updating the helper function `generate_random_numpy_array()` by adding an argument `order` to generate arrays in different orders Additionally Input generation for tests was changed in #2227 , now `test_fft2` and `test_fftn` do not use `order` parameter. This PR suggests to update these tests to use input data with different orders. --- dpnp/tests/helper.py | 17 +++++++++++++++-- dpnp/tests/test_fft.py | 13 +++++-------- dpnp/tests/test_linalg.py | 9 ++++----- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/dpnp/tests/helper.py b/dpnp/tests/helper.py index f7bb9cfc934..9ed778abc10 100644 --- a/dpnp/tests/helper.py +++ b/dpnp/tests/helper.py @@ -191,7 +191,13 @@ def not_excluded(dtype): def generate_random_numpy_array( - shape, dtype=None, hermitian=False, seed_value=None, low=-10, high=10 + shape, + dtype=None, + order="C", + hermitian=False, + seed_value=None, + low=-10, + high=10, ): """ Generate a random numpy array with the specified shape and dtype. @@ -207,6 +213,9 @@ def generate_random_numpy_array( Desired data-type for the output array. If not specified, data type will be determined by numpy. Default : ``None`` + order : {"C", "F"}, optional + Specify the memory layout of the output array. + Default: ``"C"``. hermitian : bool, optional If True, generates a Hermitian (symmetric if `dtype` is real) matrix. Default : ``False`` @@ -223,7 +232,7 @@ def generate_random_numpy_array( Returns ------- out : numpy.ndarray - A random numpy array of the specified shape and dtype. + A random numpy array of the specified shape, dtype and memory layout. The array is Hermitian or symmetric if `hermitian` is True. Note: @@ -256,6 +265,10 @@ def generate_random_numpy_array( a = a.reshape(orig_shape) else: a = numpy.conj(a.T) @ a + + # a.reshape(shape) returns an array in C order by default + if order != "C" and a.ndim > 1: + a = numpy.array(a, order=order) return a diff --git a/dpnp/tests/test_fft.py b/dpnp/tests/test_fft.py index 88ef7011b1b..33f81a7394d 100644 --- a/dpnp/tests/test_fft.py +++ b/dpnp/tests/test_fft.py @@ -380,7 +380,7 @@ def setup_method(self): @pytest.mark.parametrize("norm", [None, "forward", "backward", "ortho"]) @pytest.mark.parametrize("order", ["C", "F"]) def test_fft2(self, dtype, axes, norm, order): - a_np = generate_random_numpy_array((2, 3, 4), dtype) + a_np = generate_random_numpy_array((2, 3, 4), dtype, order) a = dpnp.array(a_np) result = dpnp.fft.fft2(a, axes=axes, norm=norm) @@ -442,7 +442,7 @@ def setup_method(self): @pytest.mark.parametrize("norm", [None, "backward", "forward", "ortho"]) @pytest.mark.parametrize("order", ["C", "F"]) def test_fftn(self, dtype, axes, norm, order): - a_np = generate_random_numpy_array((2, 3, 4, 5), dtype) + a_np = generate_random_numpy_array((2, 3, 4, 5), dtype, order) a = dpnp.array(a_np) result = dpnp.fft.fftn(a, axes=axes, norm=norm) @@ -696,8 +696,7 @@ def test_irfft_1D_on_2D_array(self, dtype, n, axis, norm, order): @pytest.mark.parametrize("norm", [None, "backward", "forward", "ortho"]) @pytest.mark.parametrize("order", ["C", "F"]) def test_irfft_1D_on_3D_array(self, dtype, n, axis, norm, order): - x = generate_random_numpy_array((4, 5, 6), dtype) - a_np = numpy.array(x, order=order) + a_np = generate_random_numpy_array((4, 5, 6), dtype, order) # each 1-D array of input should be Hermitian if axis == 0: a_np[0].imag = 0 @@ -937,8 +936,7 @@ def setup_method(self): @pytest.mark.parametrize("norm", [None, "backward", "forward", "ortho"]) @pytest.mark.parametrize("order", ["C", "F"]) def test_rfft2(self, dtype, axes, norm, order): - x = generate_random_numpy_array((2, 3, 4), dtype) - a_np = numpy.array(x, order=order) + a_np = generate_random_numpy_array((2, 3, 4), dtype, order) a = dpnp.asarray(a_np) result = dpnp.fft.rfft2(a, axes=axes, norm=norm) @@ -1002,8 +1000,7 @@ def setup_method(self): @pytest.mark.parametrize("norm", [None, "backward", "forward", "ortho"]) @pytest.mark.parametrize("order", ["C", "F"]) def test_rfftn(self, dtype, axes, norm, order): - x = generate_random_numpy_array((2, 3, 4, 5), dtype) - a_np = numpy.array(x, order=order) + a_np = generate_random_numpy_array((2, 3, 4, 5), dtype, order) a = dpnp.asarray(a_np) result = dpnp.fft.rfftn(a, axes=axes, norm=norm) diff --git a/dpnp/tests/test_linalg.py b/dpnp/tests/test_linalg.py index 851707ee9ca..990ab59b173 100644 --- a/dpnp/tests/test_linalg.py +++ b/dpnp/tests/test_linalg.py @@ -503,10 +503,9 @@ def test_eigenvalues(self, func, shape, dtype, order): # non-symmetric for eig() and eigvals() is_hermitian = func in ("eigh, eigvalsh") a = generate_random_numpy_array( - shape, dtype, hermitian=is_hermitian, low=-4, high=4 + shape, dtype, order, hermitian=is_hermitian, low=-4, high=4 ) - a_order = numpy.array(a, order=order) - a_dp = dpnp.array(a, order=order) + a_dp = dpnp.array(a) # NumPy with OneMKL and with rocSOLVER sorts in ascending order, # so w's should be directly comparable. @@ -514,13 +513,13 @@ def test_eigenvalues(self, func, shape, dtype, order): # constructing eigenvectors, so v's are not directly comparable and # we verify them through the eigen equation A*v=w*v. if func in ("eig", "eigh"): - w, _ = getattr(numpy.linalg, func)(a_order) + w, _ = getattr(numpy.linalg, func)(a) w_dp, v_dp = getattr(dpnp.linalg, func)(a_dp) self.assert_eigen_decomposition(a_dp, w_dp, v_dp) else: # eighvals or eigvalsh - w = getattr(numpy.linalg, func)(a_order) + w = getattr(numpy.linalg, func)(a) w_dp = getattr(dpnp.linalg, func)(a_dp) assert_dtype_allclose(w_dp, w, factor=24) From 6881425cef64b8b824673402777ed72d62449b3f Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Tue, 17 Dec 2024 09:02:21 -0800 Subject: [PATCH 06/13] address comments --- dpnp/dpnp_iface_linearalgebra.py | 5 ++- dpnp/fft/dpnp_utils_fft.py | 2 +- dpnp/tests/helper.py | 6 ++++ dpnp/tests/test_amin_amax.py | 18 ++++------ dpnp/tests/test_arraycreation.py | 9 ++--- dpnp/tests/test_histogram.py | 6 ++-- dpnp/tests/test_indexing.py | 62 ++++++++++---------------------- dpnp/tests/test_mathematical.py | 45 +++++++++-------------- dpnp/tests/test_ndarray.py | 11 +++--- dpnp/tests/test_sum.py | 3 +- dpnp/tests/test_umath.py | 11 ++---- 11 files changed, 68 insertions(+), 110 deletions(-) diff --git a/dpnp/dpnp_iface_linearalgebra.py b/dpnp/dpnp_iface_linearalgebra.py index 332085195d9..588679b3468 100644 --- a/dpnp/dpnp_iface_linearalgebra.py +++ b/dpnp/dpnp_iface_linearalgebra.py @@ -73,7 +73,10 @@ def _call_multiply(a, b, out=None): sc, arr = (a, b) if dpnp.isscalar(a) else (b, a) sc_dtype = map_dtype_to_device(type(sc), arr.sycl_device) res_dtype = dpnp.result_type(sc_dtype, arr) - res = dpnp.multiply(a, b, dtype=res_dtype) + if out is not None and out.dtype == arr.dtype: + res = dpnp.multiply(a, b, out=out) + else: + res = dpnp.multiply(a, b, dtype=res_dtype) return dpnp.get_result_array(res, out, casting="no") diff --git a/dpnp/fft/dpnp_utils_fft.py b/dpnp/fft/dpnp_utils_fft.py index 95ad5b7bbb8..43d46763f50 100644 --- a/dpnp/fft/dpnp_utils_fft.py +++ b/dpnp/fft/dpnp_utils_fft.py @@ -282,7 +282,7 @@ def _copy_array(x, complex_input): # r2c FFT, if input is integer or float16 dtype, convert to # float32 or float64 depending on device capabilities copy_flag = True - if dtype in [dpnp.float16]: + if dtype == dpnp.float16: dtype = dpnp.float32 else: dtype = map_dtype_to_device(dpnp.float64, x.sycl_device) diff --git a/dpnp/tests/helper.py b/dpnp/tests/helper.py index 9ed778abc10..1ffa208227c 100644 --- a/dpnp/tests/helper.py +++ b/dpnp/tests/helper.py @@ -142,6 +142,12 @@ def get_float_complex_dtypes(no_float16=True, device=None): return dtypes +def get_abs_array(data, dtype=None): + if numpy.issubdtype(dtype, numpy.unsignedinteger): + data = numpy.abs(data) + return numpy.array(data, dtype=dtype) + + def get_all_dtypes( no_bool=False, no_float16=True, diff --git a/dpnp/tests/test_amin_amax.py b/dpnp/tests/test_amin_amax.py index 1052fe7d77e..35f45cd4082 100644 --- a/dpnp/tests/test_amin_amax.py +++ b/dpnp/tests/test_amin_amax.py @@ -4,23 +4,19 @@ import dpnp -from .helper import get_all_dtypes +from .helper import get_abs_array, get_all_dtypes @pytest.mark.parametrize("func", ["amax", "amin"]) @pytest.mark.parametrize("keepdims", [True, False]) @pytest.mark.parametrize("dtype", get_all_dtypes()) def test_amax_amin(func, keepdims, dtype): - a = numpy.array( - [ - [[-2.0, 3.0], [9.1, 0.2]], - [[-2.0, 5.0], [-2, -1.2]], - [[1.0, -2.0], [5.0, -1.1]], - ], - ) - if numpy.issubdtype(dtype, numpy.unsignedinteger): - a = numpy.abs(a) - a = a.astype(dtype) + a = [ + [[-2.0, 3.0], [9.1, 0.2]], + [[-2.0, 5.0], [-2, -1.2]], + [[1.0, -2.0], [5.0, -1.1]], + ] + a = get_abs_array(a, dtype) ia = dpnp.array(a) for axis in range(len(a)): diff --git a/dpnp/tests/test_arraycreation.py b/dpnp/tests/test_arraycreation.py index b321401a56e..1b4d97de624 100644 --- a/dpnp/tests/test_arraycreation.py +++ b/dpnp/tests/test_arraycreation.py @@ -14,10 +14,7 @@ import dpnp -from .helper import ( - assert_dtype_allclose, - get_all_dtypes, -) +from .helper import assert_dtype_allclose, get_all_dtypes from .third_party.cupy import testing @@ -176,8 +173,8 @@ def test_exception_subok(func, args): @pytest.mark.parametrize("start", [0, -5, 10, -2.5, 9.7]) -@pytest.mark.parametrize("stop", [None, 10, -2, 20.5, 1000]) -@pytest.mark.parametrize("step", [None, 1, 2.7, -1.6, 100]) +@pytest.mark.parametrize("stop", [None, 10, -2, 20.5, 100]) +@pytest.mark.parametrize("step", [None, 1, 2.7, -1.6, 80]) @pytest.mark.parametrize( "dtype", get_all_dtypes(no_bool=True, no_float16=False) ) diff --git a/dpnp/tests/test_histogram.py b/dpnp/tests/test_histogram.py index 8950ee8df4b..24e97b1bc08 100644 --- a/dpnp/tests/test_histogram.py +++ b/dpnp/tests/test_histogram.py @@ -14,6 +14,7 @@ from .helper import ( assert_dtype_allclose, + get_abs_array, get_all_dtypes, get_float_dtypes, get_integer_dtypes, @@ -44,10 +45,10 @@ class TestDigitize: ], ) def test_digitize(self, x, bins, dtype, right): + x = get_abs_array(x, dtype) if numpy.issubdtype(dtype, numpy.unsignedinteger) and bins[0] == -4: - x = numpy.abs(x) + # bins should be monotonically increasing, cannot use get_abs_array bins = numpy.array([0, 2, 4, 6, 8]) - x = x.astype(dtype) bins = bins.astype(dtype) x_dp = dpnp.array(x) bins_dp = dpnp.array(bins) @@ -531,6 +532,7 @@ def test_rand_data(self, dtype): iv = dpnp.array(v) if numpy.issubdtype(dtype, numpy.uint64): + # discussed in numpy issue 17760 assert_raises(TypeError, numpy.bincount, v) assert_raises(ValueError, dpnp.bincount, iv) else: diff --git a/dpnp/tests/test_indexing.py b/dpnp/tests/test_indexing.py index 93c67786b95..20d9093c3e4 100644 --- a/dpnp/tests/test_indexing.py +++ b/dpnp/tests/test_indexing.py @@ -17,7 +17,12 @@ import dpnp from dpnp.dpnp_array import dpnp_array -from .helper import get_all_dtypes, get_integer_dtypes, has_support_aspect64 +from .helper import ( + get_abs_array, + get_all_dtypes, + get_integer_dtypes, + has_support_aspect64, +) from .third_party.cupy import testing @@ -122,14 +127,8 @@ def test_extract(self, dt): @pytest.mark.parametrize("a_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("cond_dt", get_all_dtypes(no_none=True)) def test_extract_diff_dtypes(self, a_dt, cond_dt): - x = [-2, -1, 0, 1, 2, 3] - y = [1, -1, 2, 0, -2, 3] - if numpy.issubdtype(a_dt, numpy.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=a_dt) - if numpy.issubdtype(cond_dt, numpy.unsignedinteger): - y = numpy.abs(y) - cond = numpy.array(y, dtype=cond_dt) + a = get_abs_array([-2, -1, 0, 1, 2, 3], a_dt) + cond = get_abs_array([1, -1, 2, 0, -2, 3], cond_dt) ia, icond = dpnp.array(a), dpnp.array(cond) result = dpnp.extract(icond, ia) @@ -459,17 +458,12 @@ class TestPut: ) @pytest.mark.parametrize("mode", ["clip", "wrap"]) def test_input_1d(self, a_dt, indices, ind_dt, vals, mode): - x = [-2, -1, 0, 1, 2] - if numpy.issubdtype(a_dt, numpy.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=a_dt) + a = get_abs_array([-2, -1, 0, 1, 2], a_dt) b = numpy.copy(a) ia = dpnp.array(a) ib = dpnp.array(b) - if numpy.issubdtype(ind_dt, numpy.unsignedinteger): - indices = numpy.abs(indices) - ind = numpy.array(indices, dtype=ind_dt) + ind = get_abs_array(indices, ind_dt) if ind_dt == dpnp.bool and ind.all(): ind[0] = False # to get rid of duplicate indices iind = dpnp.array(ind) @@ -510,16 +504,11 @@ def test_input_1d(self, a_dt, indices, ind_dt, vals, mode): @pytest.mark.parametrize("ind_dt", get_integer_dtypes()) @pytest.mark.parametrize("mode", ["clip", "wrap"]) def test_input_2d(self, a_dt, indices, ind_dt, mode): - x = [[-1, 0, 1], [-2, -3, -4], [2, 3, 4]] - if numpy.issubdtype(a_dt, numpy.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=a_dt) + a = get_abs_array([[-1, 0, 1], [-2, -3, -4], [2, 3, 4]], a_dt) ia = dpnp.array(a) vals = [10, 20] - if numpy.issubdtype(ind_dt, numpy.unsignedinteger): - indices = numpy.abs(indices) - ind = numpy.array(indices, dtype=ind_dt) + ind = get_abs_array(indices, ind_dt) iind = dpnp.array(ind) if numpy.issubdtype(ind_dt, numpy.uint64): @@ -707,13 +696,8 @@ class TestTake: ) @pytest.mark.parametrize("mode", ["clip", "wrap"]) def test_1d(self, a_dt, ind_dt, indices, mode): - x = [-2, -1, 0, 1, 2] - if numpy.issubdtype(a_dt, numpy.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=a_dt) - if numpy.issubdtype(ind_dt, numpy.unsignedinteger): - indices = numpy.abs(indices) - ind = numpy.array(indices, dtype=ind_dt) + a = get_abs_array([-2, -1, 0, 1, 2], a_dt) + ind = get_abs_array(indices, ind_dt) ia, iind = dpnp.array(a), dpnp.array(ind) if numpy.can_cast(ind_dt, numpy.intp, casting="safe"): @@ -739,13 +723,8 @@ def test_1d(self, a_dt, ind_dt, indices, mode): @pytest.mark.parametrize("mode", ["clip", "wrap"]) @pytest.mark.parametrize("axis", [0, 1]) def test_2d(self, a_dt, ind_dt, indices, mode, axis): - x = [[-1, 0, 1], [-2, -3, -4], [2, 3, 4]] - if numpy.issubdtype(a_dt, numpy.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=a_dt) - if numpy.issubdtype(ind_dt, numpy.unsignedinteger): - indices = numpy.abs(indices) - ind = numpy.array(indices, dtype=ind_dt) + a = get_abs_array([[-1, 0, 1], [-2, -3, -4], [2, 3, 4]], a_dt) + ind = get_abs_array(indices, ind_dt) ia, iind = dpnp.array(a), dpnp.array(ind) if numpy.issubdtype(ind_dt, numpy.uint64): @@ -761,16 +740,11 @@ def test_2d(self, a_dt, ind_dt, indices, mode, axis): @pytest.mark.parametrize("a_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("mode", ["clip", "wrap"]) def test_over_index(self, a_dt, mode): - x = [-2, -1, 0, 1, 2] - y = [-2, 2] - if numpy.issubdtype(a_dt, numpy.unsignedinteger): - x = numpy.abs(x) - y = numpy.abs(y) - a = dpnp.array(x, dtype=a_dt) + a = get_abs_array([-2, -1, 0, 1, 2], a_dt) ind = dpnp.array([-5, 5], dtype=numpy.intp) result = dpnp.take(a, ind, mode=mode) - expected = dpnp.array(y, dtype=a.dtype) + expected = get_abs_array([-2, 2], a_dt) assert_array_equal(result, expected) @pytest.mark.parametrize("xp", [numpy, dpnp]) diff --git a/dpnp/tests/test_mathematical.py b/dpnp/tests/test_mathematical.py index ee139a77d6a..db62730fa6b 100644 --- a/dpnp/tests/test_mathematical.py +++ b/dpnp/tests/test_mathematical.py @@ -24,6 +24,7 @@ from .helper import ( assert_dtype_allclose, generate_random_numpy_array, + get_abs_array, get_all_dtypes, get_complex_dtypes, get_float_complex_dtypes, @@ -40,8 +41,8 @@ from .third_party.cupy import testing +@pytest.mark.parametrize("deg", [True, False]) class TestAngle: - @pytest.mark.parametrize("deg", [True, False]) def test_angle_bool(self, deg): dp_a = dpnp.array([True, False]) np_a = dp_a.asnumpy() @@ -57,7 +58,6 @@ def test_angle_bool(self, deg): @pytest.mark.parametrize( "dtype", get_all_dtypes(no_bool=True, no_complex=True) ) - @pytest.mark.parametrize("deg", [True, False]) def test_angle(self, dtype, deg): dp_a = dpnp.arange(10, dtype=dtype) np_a = dp_a.asnumpy() @@ -69,7 +69,6 @@ def test_angle(self, dtype, deg): assert_dtype_allclose(result, expected, check_only_type_kind=True) @pytest.mark.parametrize("dtype", get_complex_dtypes()) - @pytest.mark.parametrize("deg", [True, False]) def test_angle_complex(self, dtype, deg): a = numpy.random.rand(10) b = numpy.random.rand(10) @@ -874,10 +873,7 @@ class TestFix: "dt", get_all_dtypes(no_none=True, no_complex=True) ) def test_basic(self, dt): - x = [[1.0, 1.1, 1.5, 1.8], [-1.0, -1.1, -1.5, -1.8]] - if dpnp.issubdtype(dt, dpnp.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=dt) + a = get_abs_array([[1.0, 1.1, 1.5, 1.8], [-1.0, -1.1, -1.5, -1.8]], dt) ia = dpnp.array(a) result = dpnp.fix(ia) @@ -895,10 +891,9 @@ def test_complex(self, xp, dt): "a_dt", get_all_dtypes(no_none=True, no_bool=True, no_complex=True) ) def test_out(self, a_dt): - x = [[1.0, 1.1, 1.5, 1.8], [-1.0, -1.1, -1.5, -1.8]] - if dpnp.issubdtype(a_dt, dpnp.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=a_dt) + a = get_abs_array( + [[1.0, 1.1, 1.5, 1.8], [-1.0, -1.1, -1.5, -1.8]], a_dt + ) ia = dpnp.array(a) out_dt = _get_output_data_type(a.dtype) @@ -1299,13 +1294,8 @@ def test_basic(self, val, dt): "b_dt", get_all_dtypes(no_none=True, no_complex=True) ) def test_both_input_as_arrays(self, a_dt, b_dt): - x = [-1.5, 0, 2.0] - y = [-0, 0.5, 1.0] - if numpy.issubdtype(a_dt, numpy.unsignedinteger): - x = numpy.abs(x) - y = numpy.abs(y) - a = numpy.array(x, dtype=a_dt) - b = numpy.array(y, dtype=b_dt) + a = get_abs_array([-1.5, 0, 2.0], a_dt) + b = get_abs_array([-0, 0.5, 1.0], b_dt) ia, ib = dpnp.array(a), dpnp.array(b) result = dpnp.heaviside(ia, ib) @@ -1359,9 +1349,11 @@ def test_1d(self, dt): result = dpnp.i0(ia) expected = numpy.i0(a) - # numpy promotes result for integer inputs to float64 dtype, but dpnp + # NumPy promotes result of integer inputs to float64, but dpnp # follows Type Promotion Rules - assert_dtype_allclose(result, expected, check_only_type_kind=True) + skip_dtype = [numpy.int8, numpy.int16, numpy.uint8, numpy.uint16] + flag = True if dt in skip_dtype else False + assert_dtype_allclose(result, expected, check_only_type_kind=flag) @pytest.mark.parametrize("dt", get_float_dtypes()) def test_2d(self, dt): @@ -1429,10 +1421,10 @@ def test_basic(self, mant_dt, exp_dt): if dpnp.issubdtype(exp_dt, dpnp.uint64): assert_raises(ValueError, dpnp.ldexp, imant, iexp) assert_raises(TypeError, numpy.ldexp, mant, exp) - elif dpnp.issubdtype(exp_dt, dpnp.uint32): - # For this special case, NumPy raises an error on Windows - # because it doesn't have a loop for the input types - # dpnp works fine + elif numpy.lib.NumpyVersion( + numpy.__version__ + ) < "2.0.0" and dpnp.issubdtype(exp_dt, dpnp.uint32): + # For this special case, NumPy < "2.0.0" raises an error on Windows result = dpnp.ldexp(imant, iexp) expected = numpy.ldexp(mant, exp.astype(numpy.int32)) assert_almost_equal(result, expected) @@ -2178,10 +2170,7 @@ def test_fp16(self): @pytest.mark.parametrize("dt", get_integer_dtypes()) def test_integer(self, dt): - x = [1, 0, -3] - if dpnp.issubdtype(dt, dpnp.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=dt) + a = get_abs_array([1, 0, -3], dt) ia = dpnp.array(a) result = dpnp.spacing(ia) diff --git a/dpnp/tests/test_ndarray.py b/dpnp/tests/test_ndarray.py index 1ceaebd5dbc..3d3c3ee8b63 100644 --- a/dpnp/tests/test_ndarray.py +++ b/dpnp/tests/test_ndarray.py @@ -6,6 +6,7 @@ import dpnp from .helper import ( + get_abs_array, get_all_dtypes, get_complex_dtypes, get_float_dtypes, @@ -23,9 +24,7 @@ ids=["[-2, -1, 0, 1, 2]", "[[-2, -1], [1, 2]]", "[]"], ) def test_astype(arr, arr_dtype, res_dtype): - if numpy.issubdtype(arr_dtype, numpy.unsignedinteger): - arr = numpy.abs(arr) - numpy_array = numpy.array(arr, dtype=arr_dtype) + numpy_array = get_abs_array(arr, arr_dtype) dpnp_array = dpnp.array(numpy_array) expected = numpy_array.astype(res_dtype) result = dpnp_array.astype(res_dtype) @@ -45,10 +44,8 @@ def test_astype_subok_error(): ids=["[-2, -1, 0, 1, 2]", "[[-2, -1], [1, 2]]", "[]"], ) def test_flatten(arr, arr_dtype): - if numpy.issubdtype(arr_dtype, numpy.unsignedinteger): - arr = numpy.abs(arr) - numpy_array = numpy.array(arr, dtype=arr_dtype) - dpnp_array = dpnp.array(arr, dtype=arr_dtype) + numpy_array = get_abs_array(arr, arr_dtype) + dpnp_array = dpnp.array(numpy_array) expected = numpy_array.flatten() result = dpnp_array.flatten() assert_array_equal(expected, result) diff --git a/dpnp/tests/test_sum.py b/dpnp/tests/test_sum.py index e63c3a768ea..4597cf3f5af 100644 --- a/dpnp/tests/test_sum.py +++ b/dpnp/tests/test_sum.py @@ -37,8 +37,7 @@ @pytest.mark.parametrize("keepdims", [True, False]) @pytest.mark.parametrize("order", ["C", "F"]) def test_sum(shape, dtype_in, dtype_out, transpose, keepdims, order): - a_np = generate_random_numpy_array(shape, dtype_in) - a_np = numpy.array(a_np, order=order) + a_np = generate_random_numpy_array(shape, dtype_in, order) a = dpnp.asarray(a_np) if transpose: diff --git a/dpnp/tests/test_umath.py b/dpnp/tests/test_umath.py index 01cc3f12297..46ab9681e5d 100644 --- a/dpnp/tests/test_umath.py +++ b/dpnp/tests/test_umath.py @@ -12,6 +12,7 @@ from .helper import ( assert_dtype_allclose, + get_abs_array, get_all_dtypes, get_float_complex_dtypes, get_float_dtypes, @@ -325,10 +326,7 @@ class TestDegrees: "dtype", get_all_dtypes(no_none=True, no_complex=True) ) def test_basic(self, dtype): - x = [numpy.pi, -0.5 * numpy.pi] - if numpy.issubdtype(dtype, numpy.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=dtype) + a = get_abs_array([numpy.pi, -0.5 * numpy.pi], dtype) ia = dpnp.array(a) result = dpnp.degrees(ia) @@ -524,10 +522,7 @@ class TestRadians: "dtype", get_all_dtypes(no_none=True, no_complex=True) ) def test_basic(self, dtype): - x = [120.0, -90.0] - if numpy.issubdtype(dtype, numpy.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=dtype) + a = get_abs_array([120.0, -90.0], dtype) ia = dpnp.array(a) result = dpnp.radians(ia) From b913df86cdb6e0ff11089e897c77bcf2dc83a4c8 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Tue, 17 Dec 2024 11:12:33 -0800 Subject: [PATCH 07/13] test_over_index --- dpnp/tests/test_indexing.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dpnp/tests/test_indexing.py b/dpnp/tests/test_indexing.py index 20d9093c3e4..2e197fa6993 100644 --- a/dpnp/tests/test_indexing.py +++ b/dpnp/tests/test_indexing.py @@ -741,6 +741,7 @@ def test_2d(self, a_dt, ind_dt, indices, mode, axis): @pytest.mark.parametrize("mode", ["clip", "wrap"]) def test_over_index(self, a_dt, mode): a = get_abs_array([-2, -1, 0, 1, 2], a_dt) + a = dpnp.array(a) ind = dpnp.array([-5, 5], dtype=numpy.intp) result = dpnp.take(a, ind, mode=mode) From 2619205ead91b901cd4c7e8bdd5113cd4f0f3591 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Wed, 18 Dec 2024 02:23:26 -0800 Subject: [PATCH 08/13] address new comments --- dpnp/tests/test_histogram.py | 8 +++++--- dpnp/tests/test_indexing.py | 10 ++-------- dpnp/tests/test_mathematical.py | 16 ++++++---------- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/dpnp/tests/test_histogram.py b/dpnp/tests/test_histogram.py index 24e97b1bc08..3a87fc2402f 100644 --- a/dpnp/tests/test_histogram.py +++ b/dpnp/tests/test_histogram.py @@ -46,9 +46,11 @@ class TestDigitize: ) def test_digitize(self, x, bins, dtype, right): x = get_abs_array(x, dtype) - if numpy.issubdtype(dtype, numpy.unsignedinteger) and bins[0] == -4: - # bins should be monotonically increasing, cannot use get_abs_array - bins = numpy.array([0, 2, 4, 6, 8]) + if numpy.issubdtype(dtype, numpy.unsignedinteger): + min_bin = bins.min() + if min_bin < 0: + # bins should be monotonically increasing, cannot use get_abs_array + bins -= min_bin bins = bins.astype(dtype) x_dp = dpnp.array(x) bins_dp = dpnp.array(bins) diff --git a/dpnp/tests/test_indexing.py b/dpnp/tests/test_indexing.py index 2e197fa6993..545377afb78 100644 --- a/dpnp/tests/test_indexing.py +++ b/dpnp/tests/test_indexing.py @@ -137,10 +137,7 @@ def test_extract_diff_dtypes(self, a_dt, cond_dt): @pytest.mark.parametrize("a_dt", get_all_dtypes(no_none=True)) def test_extract_list_cond(self, a_dt): - x = [-2, -1, 0, 1, 2, 3] - if numpy.issubdtype(a_dt, numpy.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=a_dt) + a = get_abs_array([-2, -1, 0, 1, 2, 3], a_dt) cond = [1, -1, 2, 0, -2, 3] ia = dpnp.array(a) @@ -393,10 +390,7 @@ def test_0d(self, val): @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) def test_1d(self, dtype): - x = [1, 0, 2, -1, 0, 0, 8] - if numpy.issubdtype(dtype, numpy.unsignedinteger): - x = numpy.abs(x) - a = numpy.array(x, dtype=dtype) + a = get_abs_array([1, 0, 2, -1, 0, 0, 8], dtype) ia = dpnp.array(a) np_res = numpy.nonzero(a) diff --git a/dpnp/tests/test_mathematical.py b/dpnp/tests/test_mathematical.py index db62730fa6b..15fdbc01ffc 100644 --- a/dpnp/tests/test_mathematical.py +++ b/dpnp/tests/test_mathematical.py @@ -32,6 +32,7 @@ get_integer_dtypes, has_support_aspect16, has_support_aspect64, + numpy_version, ) from .test_umath import ( _get_numpy_arrays_1in_1out, @@ -1408,7 +1409,7 @@ class TestLdexp: @pytest.mark.parametrize("exp_dt", get_integer_dtypes()) def test_basic(self, mant_dt, exp_dt): if ( - numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0" + numpy_version() < "2.0.0" and exp_dt == numpy.int64 and numpy.dtype("l") != numpy.int64 ): @@ -1421,9 +1422,7 @@ def test_basic(self, mant_dt, exp_dt): if dpnp.issubdtype(exp_dt, dpnp.uint64): assert_raises(ValueError, dpnp.ldexp, imant, iexp) assert_raises(TypeError, numpy.ldexp, mant, exp) - elif numpy.lib.NumpyVersion( - numpy.__version__ - ) < "2.0.0" and dpnp.issubdtype(exp_dt, dpnp.uint32): + elif numpy_version() < "2.0.0" and dpnp.issubdtype(exp_dt, dpnp.uint32): # For this special case, NumPy < "2.0.0" raises an error on Windows result = dpnp.ldexp(imant, iexp) expected = numpy.ldexp(mant, exp.astype(numpy.int32)) @@ -2130,7 +2129,7 @@ def test_zeros(self, dt): result = dpnp.spacing(ia) expected = numpy.spacing(a) - if numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0": + if numpy_version() < "2.0.0": assert_equal(result, expected) else: # numpy.spacing(-0.0) == numpy.spacing(0.0), i.e. NumPy returns @@ -2193,7 +2192,7 @@ def test_complex(self, xp): class TestTrapezoid: def get_numpy_func(self): - if numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0": + if numpy_version() < "2.0.0": # `trapz` is deprecated in NumPy 2.0 return numpy.trapz return numpy.trapezoid @@ -2753,10 +2752,7 @@ def test_out(self, func_params, dtype): # NumPy < 2.0.0 while output has the dtype of input for NumPy >= 2.0.0 # (dpnp follows the latter behavior except for boolean dtype where it # returns int8) - if ( - numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0" - or dtype == numpy.bool - ): + if numpy_version() < "2.0.0" or dtype == numpy.bool: check_type = False else: check_type = True From ea16c17f988ab6a164da2a42b3c9827fe9527671 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Wed, 18 Dec 2024 05:51:45 -0800 Subject: [PATCH 09/13] fix issues --- dpnp/tests/test_indexing.py | 10 +++++++--- dpnp/tests/test_mathematical.py | 22 +++++++++++----------- dpnp/tests/test_product.py | 7 +++++-- dpnp/tests/test_strides.py | 27 ++++++--------------------- dpnp/tests/test_sum.py | 11 +++++++---- 5 files changed, 36 insertions(+), 41 deletions(-) diff --git a/dpnp/tests/test_indexing.py b/dpnp/tests/test_indexing.py index 545377afb78..80c1fdd40b9 100644 --- a/dpnp/tests/test_indexing.py +++ b/dpnp/tests/test_indexing.py @@ -22,6 +22,8 @@ get_all_dtypes, get_integer_dtypes, has_support_aspect64, + is_win_platform, + numpy_version, ) from .third_party.cupy import testing @@ -700,10 +702,12 @@ def test_1d(self, a_dt, ind_dt, indices, mode): assert_array_equal(result, expected) elif numpy.issubdtype(ind_dt, numpy.uint64): # For this special case, although casting `ind_dt` to numpy.intp - # is not safe, dpnp do not raise an error - # NumPy only raises an error on Windows + # is not safe, both NumPy and dpnp work properly + # NumPy < "2.2.0" raises an error on Windows + if numpy_version() < "2.2.0" and is_win_platform(): + ind = ind.astype(numpy.int64) result = dpnp.take(ia, iind, mode=mode) - expected = numpy.take(a, ind.astype(numpy.int64), mode=mode) + expected = numpy.take(a, ind, mode=mode) assert_array_equal(result, expected) else: assert_raises(TypeError, ia.take, iind, mode=mode) diff --git a/dpnp/tests/test_mathematical.py b/dpnp/tests/test_mathematical.py index 15fdbc01ffc..737b3c4d63f 100644 --- a/dpnp/tests/test_mathematical.py +++ b/dpnp/tests/test_mathematical.py @@ -67,7 +67,8 @@ def test_angle(self, dtype, deg): result = dpnp.angle(dp_a, deg=deg) # For dtype=int8, uint8, NumPy returns float16, but dpnp returns float32 - assert_dtype_allclose(result, expected, check_only_type_kind=True) + dt_int8 = dtype in [dpnp.int8, dpnp.uint8] + assert_dtype_allclose(result, expected, check_only_type_kind=dt_int8) @pytest.mark.parametrize("dtype", get_complex_dtypes()) def test_angle_complex(self, dtype, deg): @@ -1352,8 +1353,7 @@ def test_1d(self, dt): expected = numpy.i0(a) # NumPy promotes result of integer inputs to float64, but dpnp # follows Type Promotion Rules - skip_dtype = [numpy.int8, numpy.int16, numpy.uint8, numpy.uint16] - flag = True if dt in skip_dtype else False + flag = dt in [numpy.int8, numpy.int16, numpy.uint8, numpy.uint16] assert_dtype_allclose(result, expected, check_only_type_kind=flag) @pytest.mark.parametrize("dt", get_float_dtypes()) @@ -2034,7 +2034,8 @@ def test_basic(self, dt): expected = numpy.sinc(a) # numpy promotes result for integer inputs to float64 dtype, but dpnp # follows Type Promotion Rules similar to other trigonometric functions - assert_dtype_allclose(result, expected, check_only_type_kind=True) + flag = dt in [numpy.int8, numpy.int16, numpy.uint8, numpy.uint16] + assert_dtype_allclose(result, expected, check_only_type_kind=flag) def test_bool(self): a = numpy.array([True, False, True]) @@ -2054,7 +2055,8 @@ def test_zero(self, dt): expected = numpy.sinc(a) # numpy promotes result for integer inputs to float64 dtype, but dpnp # follows Type Promotion Rules similar to other trigonometric functions - assert_dtype_allclose(result, expected, check_only_type_kind=True) + flag = dt in [numpy.int8, numpy.int16, numpy.uint8, numpy.uint16] + assert_dtype_allclose(result, expected, check_only_type_kind=flag) # TODO: add a proper NumPy version once resolved @testing.with_requires("numpy>=2.0.0") @@ -2499,7 +2501,7 @@ def test_divide_scalar(shape, dtype): ) def test_negative(data, dtype): np_a = numpy.array(data, dtype=dtype) - dpnp_a = dpnp.array(data, dtype=dtype) + dpnp_a = dpnp.array(np_a) result = dpnp.negative(dpnp_a) expected = numpy.negative(np_a) @@ -2529,12 +2531,10 @@ def test_negative_boolean(): [[[1.0, -1.0], [0.1, -0.1]], [-2, -1, 0, 1, 2]], ids=["[[1., -1.], [0.1, -0.1]]", "[-2, -1, 0, 1, 2]"], ) -@pytest.mark.parametrize( - "dtype", get_all_dtypes(no_bool=True, no_unsigned=True) -) +@pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True)) def test_positive(data, dtype): - np_a = numpy.array(data, dtype=dtype) - dpnp_a = dpnp.array(data, dtype=dtype) + np_a = get_abs_array(data, dtype=dtype) + dpnp_a = dpnp.array(np_a) result = dpnp.positive(dpnp_a) expected = numpy.positive(np_a) diff --git a/dpnp/tests/test_product.py b/dpnp/tests/test_product.py index b9b199b0d28..2bba4c0f322 100644 --- a/dpnp/tests/test_product.py +++ b/dpnp/tests/test_product.py @@ -12,6 +12,8 @@ generate_random_numpy_array, get_all_dtypes, get_complex_dtypes, + is_win_platform, + numpy_version, ) from .third_party.cupy import testing @@ -508,8 +510,9 @@ def test_scalar(self, dtype): result = dpnp.kron(ib, a) expected = numpy.kron(b, a) - # NumPy returns incorrect dtype on Windows, add check_type=False - assert_dtype_allclose(result, expected, check_type=False) + # NumPy returns incorrect dtype on Windows + flag = not is_win_platform() if numpy_version() < "2.0.0" else True + assert_dtype_allclose(result, expected, check_type=flag) @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( diff --git a/dpnp/tests/test_strides.py b/dpnp/tests/test_strides.py index f9cb3d52018..beacf6109fa 100644 --- a/dpnp/tests/test_strides.py +++ b/dpnp/tests/test_strides.py @@ -163,13 +163,8 @@ def test_logsumexp(dtype): expected = numpy.logaddexp.reduce(a) # for int8, uint8, NumPy returns float16 but dpnp returns float64 # for int16, uint16, NumPy returns float32 but dpnp returns float64 - if dtype in [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16]: - check_only_type_kind = True - else: - check_only_type_kind = False - assert_dtype_allclose( - result, expected, check_only_type_kind=check_only_type_kind - ) + flag = dtype in [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16] + assert_dtype_allclose(result, expected, check_only_type_kind=flag) @pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True, no_complex=True)) @@ -181,13 +176,8 @@ def test_cumlogsumexp(dtype): expected = numpy.logaddexp.accumulate(a) # for int8, uint8, NumPy returns float16 but dpnp returns float64 # for int16, uint16, NumPy returns float32 but dpnp returns float64 - if dtype in [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16]: - check_only_type_kind = True - else: - check_only_type_kind = False - assert_dtype_allclose( - result, expected, check_only_type_kind=check_only_type_kind - ) + flag = dtype in [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16] + assert_dtype_allclose(result, expected, check_only_type_kind=flag) @pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True, no_complex=True)) @@ -199,13 +189,8 @@ def test_reduce_hypot(dtype): expected = numpy.hypot.reduce(a) # for int8, uint8, NumPy returns float16 but dpnp returns float64 # for int16, uint16, NumPy returns float32 but dpnp returns float64 - if dtype in [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16]: - check_only_type_kind = True - else: - check_only_type_kind = False - assert_dtype_allclose( - result, expected, check_only_type_kind=check_only_type_kind - ) + flag = dtype in [dpnp.int8, dpnp.uint8, dpnp.int16, dpnp.uint16] + assert_dtype_allclose(result, expected, check_only_type_kind=flag) @pytest.mark.parametrize( diff --git a/dpnp/tests/test_sum.py b/dpnp/tests/test_sum.py index 4597cf3f5af..9db08b08a63 100644 --- a/dpnp/tests/test_sum.py +++ b/dpnp/tests/test_sum.py @@ -51,12 +51,15 @@ def test_sum(shape, dtype_in, dtype_out, transpose, keepdims, order): axes.append(tuple(axes_range)) for axis in axes: - if numpy.issubdtype(dtype_out, numpy.bool_): + if ( + numpy.issubdtype(dtype_out, numpy.bool_) + and numpy.issubdtype(dtype_in, numpy.signedinteger) + and not a_np.sum(axis=axis).all() + ): # If summation is zero and dtype=numpy.bool is passed to numpy.sum # NumPy returns True which is not correct - numpy_res = a_np.sum(axis=axis, keepdims=keepdims).astype( - numpy.bool_ - ) + numpy_res = a_np.sum(axis=axis, keepdims=keepdims) + numpy_res = numpy_res.astype(numpy.bool_) else: numpy_res = a_np.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) dpnp_res = a.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) From 2bea89630502bc7a544e2e5e6158eade16e3b831 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Wed, 18 Dec 2024 07:53:37 -0800 Subject: [PATCH 10/13] fix TestKron, TestTake, and avoid warnings --- dpnp/tests/test_indexing.py | 4 ++-- dpnp/tests/test_nanfunctions.py | 7 ++++--- dpnp/tests/test_product.py | 5 +++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/dpnp/tests/test_indexing.py b/dpnp/tests/test_indexing.py index 80c1fdd40b9..02c6ff15a49 100644 --- a/dpnp/tests/test_indexing.py +++ b/dpnp/tests/test_indexing.py @@ -703,8 +703,8 @@ def test_1d(self, a_dt, ind_dt, indices, mode): elif numpy.issubdtype(ind_dt, numpy.uint64): # For this special case, although casting `ind_dt` to numpy.intp # is not safe, both NumPy and dpnp work properly - # NumPy < "2.2.0" raises an error on Windows - if numpy_version() < "2.2.0" and is_win_platform(): + # NumPy < "2.2.0" raises an error + if numpy_version() < "2.2.0": ind = ind.astype(numpy.int64) result = dpnp.take(ia, iind, mode=mode) expected = numpy.take(a, ind, mode=mode) diff --git a/dpnp/tests/test_nanfunctions.py b/dpnp/tests/test_nanfunctions.py index 9d516cb6fba..a8eccc81c87 100644 --- a/dpnp/tests/test_nanfunctions.py +++ b/dpnp/tests/test_nanfunctions.py @@ -15,6 +15,7 @@ from .helper import ( assert_dtype_allclose, + get_abs_array, get_all_dtypes, get_complex_dtypes, get_float_complex_dtypes, @@ -648,7 +649,7 @@ class TestNanStd: ) def test_nanstd(self, array, dtype): try: - a = numpy.array(array, dtype=dtype) + a = get_abs_array(array, dtype=dtype) except: pytest.skip("floating datat type is needed to store NaN") ia = dpnp.array(a) @@ -835,9 +836,9 @@ class TestNanVar: ) def test_nanvar(self, array, dtype): try: - a = numpy.array(array, dtype=dtype) + a = get_abs_array(array, dtype=dtype) except: - pytest.skip("floating datat type is needed to store NaN") + pytest.skip("floating data type is needed to store NaN") ia = dpnp.array(a) for ddof in range(a.ndim): expected = numpy.nanvar(a, ddof=ddof) diff --git a/dpnp/tests/test_product.py b/dpnp/tests/test_product.py index 2bba4c0f322..762d2dbb992 100644 --- a/dpnp/tests/test_product.py +++ b/dpnp/tests/test_product.py @@ -510,8 +510,9 @@ def test_scalar(self, dtype): result = dpnp.kron(ib, a) expected = numpy.kron(b, a) - # NumPy returns incorrect dtype on Windows - flag = not is_win_platform() if numpy_version() < "2.0.0" else True + # NumPy returns incorrect dtype for numpy_version() < "2.0.0" + flag = dtype in [numpy.int64, numpy.float64, numpy.complex128] + flag = flag or numpy_version() >= "2.0.0" assert_dtype_allclose(result, expected, check_type=flag) @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) From 141067b27211f2be412f18b582dea97b7daf519b Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Fri, 20 Dec 2024 07:01:57 -0800 Subject: [PATCH 11/13] update test_sum.py --- dpnp/tests/test_sum.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dpnp/tests/test_sum.py b/dpnp/tests/test_sum.py index 9db08b08a63..dbe08edf881 100644 --- a/dpnp/tests/test_sum.py +++ b/dpnp/tests/test_sum.py @@ -58,11 +58,11 @@ def test_sum(shape, dtype_in, dtype_out, transpose, keepdims, order): ): # If summation is zero and dtype=numpy.bool is passed to numpy.sum # NumPy returns True which is not correct - numpy_res = a_np.sum(axis=axis, keepdims=keepdims) - numpy_res = numpy_res.astype(numpy.bool_) + a = a.astype(dpnp.bool) + dpnp_res = a.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) else: - numpy_res = a_np.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) - dpnp_res = a.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) + dpnp_res = a.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) + numpy_res = a_np.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) assert_dtype_allclose(dpnp_res, numpy_res, factor=16) From ebe48683c928d04b15dfd8210350631c1972f14b Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Fri, 20 Dec 2024 07:09:20 -0800 Subject: [PATCH 12/13] update comment --- dpnp/tests/test_sum.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dpnp/tests/test_sum.py b/dpnp/tests/test_sum.py index dbe08edf881..54a998bfa3a 100644 --- a/dpnp/tests/test_sum.py +++ b/dpnp/tests/test_sum.py @@ -56,8 +56,7 @@ def test_sum(shape, dtype_in, dtype_out, transpose, keepdims, order): and numpy.issubdtype(dtype_in, numpy.signedinteger) and not a_np.sum(axis=axis).all() ): - # If summation is zero and dtype=numpy.bool is passed to numpy.sum - # NumPy returns True which is not correct + # TODO: remove workaround when dpctl-issue#1944 is resolved a = a.astype(dpnp.bool) dpnp_res = a.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) else: From bca57d5f905563e96014b8aba8bad344ff771ef0 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad <120411540+vtavana@users.noreply.github.com> Date: Thu, 23 Jan 2025 13:57:50 -0600 Subject: [PATCH 13/13] update third party tests for newly added integr dtypes (int8, int16, uint8-uint64) (#2239) In this PR, third party tests are update to pass with newly added integer dtypes (int8, int16, uint8, uint16, uint32, uint64). This PR is in continuation of https://github.com/IntelPython/dpnp/pull/2233. --- .github/workflows/conda-package.yml | 2 +- dpnp/dpnp_algo/dpnp_elementwise_common.py | 11 ++-- dpnp/dpnp_iface_manipulation.py | 13 +++++ dpnp/tests/test_sycl_queue.py | 1 + dpnp/tests/test_usm_type.py | 1 + .../cupy/core_tests/test_elementwise.py | 46 ++++++++++----- .../core_tests/test_ndarray_complex_ops.py | 5 +- .../core_tests/test_ndarray_copy_and_view.py | 2 +- .../cupy/creation_tests/test_ranges.py | 8 ++- .../cupy/indexing_tests/test_indexing.py | 4 ++ .../cupy/linalg_tests/test_einsum.py | 16 ++++-- .../cupy/linalg_tests/test_product.py | 27 +++++---- .../cupy/logic_tests/test_comparison.py | 3 +- .../cupy/math_tests/test_matmul.py | 19 ++++--- .../third_party/cupy/math_tests/test_misc.py | 3 +- .../cupy/math_tests/test_trigonometric.py | 4 +- .../cupy/random_tests/test_permutations.py | 30 ++++++++++ .../cupy/sorting_tests/test_sort.py | 3 + dpnp/tests/third_party/cupy/testing/_loops.py | 57 ++++++++++++++----- 19 files changed, 192 insertions(+), 63 deletions(-) diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index d4754ff151c..c1b6d797875 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -529,7 +529,7 @@ jobs: env: DPNP_TEST_ALL_INT_TYPES: 1 run: | - pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests upload: name: Upload ['${{ matrix.os }}', python='${{ matrix.python }}'] diff --git a/dpnp/dpnp_algo/dpnp_elementwise_common.py b/dpnp/dpnp_algo/dpnp_elementwise_common.py index 6cb603fb480..71cd1ba5a18 100644 --- a/dpnp/dpnp_algo/dpnp_elementwise_common.py +++ b/dpnp/dpnp_algo/dpnp_elementwise_common.py @@ -590,12 +590,13 @@ def __init__( def __call__(self, x, decimals=0, out=None, dtype=None): if decimals != 0: x_usm = dpnp.get_usm_ndarray(x) - if dpnp.issubdtype(x_usm.dtype, dpnp.integer) and dtype is None: - dtype = x_usm.dtype - out_usm = None if out is None else dpnp.get_usm_ndarray(out) - x_usm = dpt.round(x_usm * 10**decimals, out=out_usm) - res_usm = dpt.divide(x_usm, 10**decimals, out=out_usm) + + if dpnp.issubdtype(x_usm.dtype, dpnp.integer): + res_usm = dpt.round(x_usm, out=out_usm) + else: + x_usm = dpt.round(x_usm * 10**decimals, out=out_usm) + res_usm = dpt.divide(x_usm, 10**decimals, out=out_usm) if dtype is not None: res_usm = dpt.astype(res_usm, dtype, copy=False) diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index 401b7c67a7f..e53b3bf9243 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -1469,7 +1469,20 @@ def copyto(dst, src, casting="same_kind", where=True): f"but got {type(dst)}" ) if not dpnp.is_supported_array_type(src): + no_dtype_attr = not hasattr(src, "dtype") src = dpnp.array(src, sycl_queue=dst.sycl_queue) + if no_dtype_attr: + # This case (scalar, list, etc) needs special handling to + # behave similar to NumPy + if dpnp.issubdtype(src, dpnp.integer) and dpnp.issubdtype( + dst, dpnp.unsignedinteger + ): + if dpnp.any(src < 0): + raise OverflowError( + "Cannot copy negative values to an unsigned int array" + ) + + src = src.astype(dst.dtype) if not dpnp.can_cast(src.dtype, dst.dtype, casting=casting): raise TypeError( diff --git a/dpnp/tests/test_sycl_queue.py b/dpnp/tests/test_sycl_queue.py index 9da87c3db86..ba584504d4d 100644 --- a/dpnp/tests/test_sycl_queue.py +++ b/dpnp/tests/test_sycl_queue.py @@ -810,6 +810,7 @@ def test_reduce_hypot(device): [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0], [5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0], ), + pytest.param("round", [1.234, 2.567], 2), pytest.param("searchsorted", [11, 12, 13, 14, 15], [-10, 20, 12, 13]), pytest.param( "subtract", diff --git a/dpnp/tests/test_usm_type.py b/dpnp/tests/test_usm_type.py index e8e97d2ea38..5231c136cdf 100644 --- a/dpnp/tests/test_usm_type.py +++ b/dpnp/tests/test_usm_type.py @@ -740,6 +740,7 @@ def test_1in_1out(func, data, usm_type): pytest.param("maximum", [0.0, 1.0, 2.0], [3.0, 4.0, 5.0]), pytest.param("minimum", [0.0, 1.0, 2.0], [3.0, 4.0, 5.0]), pytest.param("nextafter", [1, 2], [2, 1]), + pytest.param("round", [1.234, 2.567], 2), pytest.param("searchsorted", [11, 12, 13, 14, 15], [-10, 20, 12, 13]), pytest.param( "tensordot", diff --git a/dpnp/tests/third_party/cupy/core_tests/test_elementwise.py b/dpnp/tests/third_party/cupy/core_tests/test_elementwise.py index 2d268e53b37..72946894820 100644 --- a/dpnp/tests/third_party/cupy/core_tests/test_elementwise.py +++ b/dpnp/tests/third_party/cupy/core_tests/test_elementwise.py @@ -4,7 +4,11 @@ import pytest import dpnp as cupy -from dpnp.tests.helper import has_support_aspect64 +from dpnp.tests.helper import ( + has_support_aspect64, + is_win_platform, + numpy_version, +) from dpnp.tests.third_party.cupy import testing @@ -94,20 +98,22 @@ class TestElementwiseType(unittest.TestCase): @testing.for_int_dtypes(no_bool=True) @testing.numpy_cupy_array_equal(accept_error=OverflowError) def test_large_int_upper_1(self, xp, dtype): - a = xp.array([0], dtype=numpy.int8) + a = xp.array([0], dtype=xp.int8) b = xp.iinfo(dtype).max return a + b @testing.for_int_dtypes(no_bool=True) @testing.numpy_cupy_array_equal(accept_error=OverflowError) def test_large_int_upper_2(self, xp, dtype): - if ( - numpy.issubdtype(dtype, numpy.unsignedinteger) - and numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0" - ): - pytest.skip("numpy promotes dtype differently") + if numpy_version() < "2.0.0": + flag = dtype in [xp.int16, xp.int32, xp.int64, xp.longlong] + if xp.issubdtype(dtype, xp.unsignedinteger) or flag: + pytest.skip("numpy doesn't raise OverflowError") + + if dtype in [xp.int8, xp.intc] and is_win_platform(): + pytest.skip("numpy promotes dtype differently") - a = xp.array([1], dtype=numpy.int8) + a = xp.array([1], dtype=xp.int8) b = xp.iinfo(dtype).max - 1 return a + b @@ -116,7 +122,7 @@ def test_large_int_upper_2(self, xp, dtype): def test_large_int_upper_3(self, xp, dtype): if ( numpy.issubdtype(dtype, numpy.unsignedinteger) - and numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0" + and numpy_version() < "2.0.0" ): pytest.skip("numpy promotes dtype differently") elif ( @@ -134,7 +140,7 @@ def test_large_int_upper_3(self, xp, dtype): def test_large_int_upper_4(self, xp, dtype): if ( numpy.issubdtype(dtype, numpy.unsignedinteger) - and numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0" + and numpy_version() < "2.0.0" ): pytest.skip("numpy promotes dtype differently") elif ( @@ -150,14 +156,28 @@ def test_large_int_upper_4(self, xp, dtype): @testing.for_int_dtypes(no_bool=True) @testing.numpy_cupy_array_equal(accept_error=OverflowError) def test_large_int_lower_1(self, xp, dtype): - a = xp.array([0], dtype=numpy.int8) + if numpy_version() < "2.0.0": + if dtype in [xp.int16, xp.int32, xp.int64, xp.longlong]: + pytest.skip("numpy doesn't raise OverflowError") + + if dtype in [xp.int8, xp.intc] and is_win_platform(): + pytest.skip("numpy promotes dtype differently") + + a = xp.array([0], dtype=xp.int8) b = xp.iinfo(dtype).min return a + b @testing.for_int_dtypes(no_bool=True) @testing.numpy_cupy_array_equal(accept_error=OverflowError) def test_large_int_lower_2(self, xp, dtype): - a = xp.array([-1], dtype=numpy.int8) + if numpy_version() < "2.0.0": + if dtype in [xp.int16, xp.int32, xp.int64, xp.longlong]: + pytest.skip("numpy doesn't raise OverflowError") + + if dtype in [xp.int8, xp.intc] and is_win_platform(): + pytest.skip("numpy promotes dtype differently") + + a = xp.array([-1], dtype=xp.int8) b = xp.iinfo(dtype).min + 1 return a + b @@ -166,7 +186,7 @@ def test_large_int_lower_2(self, xp, dtype): def test_large_int_lower_3(self, xp, dtype): if ( numpy.issubdtype(dtype, numpy.unsignedinteger) - and numpy.lib.NumpyVersion(numpy.__version__) < "2.0.0" + and numpy_version() < "2.0.0" ): pytest.skip("numpy promotes dtype differently") elif ( diff --git a/dpnp/tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py b/dpnp/tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py index 282c38b72e6..3acebaaeb3a 100644 --- a/dpnp/tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py +++ b/dpnp/tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py @@ -4,7 +4,6 @@ import pytest import dpnp as cupy -from dpnp.tests.helper import has_support_aspect64 from dpnp.tests.third_party.cupy import testing @@ -41,8 +40,10 @@ def test_conjugate_pass(self, xp, dtype): class TestAngle(unittest.TestCase): + # For dtype=int8, uint8, NumPy returns float16, but dpnp returns float32 + # so type_check=False @testing.for_all_dtypes() - @testing.numpy_cupy_array_almost_equal(type_check=has_support_aspect64()) + @testing.numpy_cupy_array_almost_equal(type_check=False) def test_angle(self, xp, dtype): x = testing.shaped_arange((2, 3), xp, dtype) return xp.angle(x) diff --git a/dpnp/tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py b/dpnp/tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py index 515243d89c5..eaf01d1b345 100644 --- a/dpnp/tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py +++ b/dpnp/tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py @@ -338,7 +338,7 @@ def test_astype_type(self, src_dtype, dst_dtype, order): b = astype_without_warning(a, dst_dtype, order=order) a_cpu = testing.shaped_arange((2, 3, 4), numpy, src_dtype) b_cpu = astype_without_warning(a_cpu, dst_dtype, order=order) - assert b.dtype.type == b_cpu.dtype.type + assert b.dtype == b_cpu.dtype @testing.for_orders("CAK") @testing.for_all_dtypes() diff --git a/dpnp/tests/third_party/cupy/creation_tests/test_ranges.py b/dpnp/tests/third_party/cupy/creation_tests/test_ranges.py index b0d209e2570..06b4ef8dc75 100644 --- a/dpnp/tests/third_party/cupy/creation_tests/test_ranges.py +++ b/dpnp/tests/third_party/cupy/creation_tests/test_ranges.py @@ -227,7 +227,13 @@ def test_linspace_mixed_start_stop2(self, xp, dtype_range, dtype_out): # TODO (ev-br): np 2.0: had to bump the default rtol on Windows # and numpy 1.26+weak promotion from 0 to 5e-6 if xp.dtype(dtype_range).kind in "u": - start = xp.array([160, 120], dtype=dtype_range) + # to avoid overflow, limit `val` to be smaller + # than xp.iinfo(dtype).max + if dtype_range == xp.uint8 or dtype_out == xp.uint8: + val = 125 + else: + val = 160 + start = xp.array([val, 120], dtype=dtype_range) else: start = xp.array([-120, 120], dtype=dtype_range) stop = 0 diff --git a/dpnp/tests/third_party/cupy/indexing_tests/test_indexing.py b/dpnp/tests/third_party/cupy/indexing_tests/test_indexing.py index a977b44bbdb..213edf0b2c0 100644 --- a/dpnp/tests/third_party/cupy/indexing_tests/test_indexing.py +++ b/dpnp/tests/third_party/cupy/indexing_tests/test_indexing.py @@ -204,6 +204,10 @@ class TestChoose(unittest.TestCase): @testing.for_all_dtypes() @testing.numpy_cupy_array_equal() def test_choose(self, xp, dtype): + # TODO: include additional dtype when dpnp#2201 is merged + dtype_list = [xp.int8, xp.int16] + if dtype in dtype_list or xp.issubdtype(dtype, xp.unsignedinteger): + pytest.skip("dpnp.choose() does not support new integer dtypes.") a = xp.array([0, 2, 1, 2]) c = testing.shaped_arange((3, 4), xp, dtype) return a.choose(c) diff --git a/dpnp/tests/third_party/cupy/linalg_tests/test_einsum.py b/dpnp/tests/third_party/cupy/linalg_tests/test_einsum.py index 0714fbc05a7..bb44b791d41 100644 --- a/dpnp/tests/third_party/cupy/linalg_tests/test_einsum.py +++ b/dpnp/tests/third_party/cupy/linalg_tests/test_einsum.py @@ -464,9 +464,8 @@ def test_scalar_float(self, xp, dtype): ) ) class TestEinSumBinaryOperation: - @testing.for_all_dtypes_combination( - ["dtype_a", "dtype_b"], no_bool=False, no_float16=False - ) + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes_combination(["dtype_a", "dtype_b"], no_int8=True) @testing.numpy_cupy_allclose( type_check=has_support_aspect64(), contiguous_check=False ) @@ -555,13 +554,18 @@ def test_scalar_2(self, xp, dtype): ) ) class TestEinSumTernaryOperation: - @testing.for_all_dtypes_combination( - ["dtype_a", "dtype_b", "dtype_c"], no_bool=False, no_float16=False - ) + + @testing.for_all_dtypes_combination(["dtype_a", "dtype_b", "dtype_c"]) @testing.numpy_cupy_allclose( type_check=has_support_aspect64(), contiguous_check=False ) def test_einsum_ternary(self, xp, dtype_a, dtype_b, dtype_c): + flag = all( + dtype in [xp.int8, xp.uint8] + for dtype in [dtype_a, dtype_b, dtype_c] + ) + if self.subscripts == "ij,jk,kl" and flag: + pytest.skip("avoid overflow") a = testing.shaped_arange(self.shape_a, xp, dtype_a) b = testing.shaped_arange(self.shape_b, xp, dtype_b) c = testing.shaped_arange(self.shape_c, xp, dtype_c) diff --git a/dpnp/tests/third_party/cupy/linalg_tests/test_product.py b/dpnp/tests/third_party/cupy/linalg_tests/test_product.py index a712c1cb032..2617e100a9c 100644 --- a/dpnp/tests/third_party/cupy/linalg_tests/test_product.py +++ b/dpnp/tests/third_party/cupy/linalg_tests/test_product.py @@ -39,8 +39,9 @@ ) ) class TestDot(unittest.TestCase): - - @testing.for_all_dtypes_combination(["dtype_a", "dtype_b"]) + # no_int8=True is added to avoid overflow for shape=((2, 3, 4), (3, 4, 2)) + # and ((2, 3), (3, 4)) cases on cpu + @testing.for_all_dtypes_combination(["dtype_a", "dtype_b"], no_int8=True) @testing.numpy_cupy_allclose(type_check=has_support_aspect64()) def test_dot(self, xp, dtype_a, dtype_b): shape_a, shape_b = self.shape @@ -238,14 +239,14 @@ def test_dot_vec3(self, xp, dtype): b = testing.shaped_arange((2,), xp, dtype) return xp.dot(a, b) - @testing.for_all_dtypes() + @testing.for_all_dtypes(no_int8=True) @testing.numpy_cupy_allclose() def test_transposed_dot(self, xp, dtype): a = testing.shaped_arange((2, 3, 4), xp, dtype).transpose(1, 0, 2) b = testing.shaped_arange((2, 3, 4), xp, dtype).transpose(0, 2, 1) return xp.dot(a, b) - @testing.for_all_dtypes() + @testing.for_all_dtypes(no_int8=True) @testing.numpy_cupy_allclose() def test_transposed_dot_with_out(self, xp, dtype): a = testing.shaped_arange((2, 3, 4), xp, dtype).transpose(1, 0, 2) @@ -320,14 +321,16 @@ def test_reversed_inner(self, xp, dtype): b = testing.shaped_reverse_arange((5,), xp, dtype)[::-1] return xp.inner(a, b) - @testing.for_all_dtypes() + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes(no_int8=True) @testing.numpy_cupy_allclose() def test_multidim_inner(self, xp, dtype): a = testing.shaped_arange((2, 3, 4), xp, dtype) b = testing.shaped_arange((3, 2, 4), xp, dtype) return xp.inner(a, b) - @testing.for_all_dtypes() + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes(no_int8=True) @testing.numpy_cupy_allclose() def test_transposed_higher_order_inner(self, xp, dtype): a = testing.shaped_arange((2, 4, 3), xp, dtype).transpose(2, 0, 1) @@ -355,14 +358,16 @@ def test_multidim_outer(self, xp, dtype): b = testing.shaped_arange((4, 5), xp, dtype) return xp.outer(a, b) - @testing.for_all_dtypes() + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes(no_int8=True) @testing.numpy_cupy_allclose() def test_tensordot(self, xp, dtype): a = testing.shaped_arange((2, 3, 4), xp, dtype) b = testing.shaped_arange((3, 4, 5), xp, dtype) return xp.tensordot(a, b) - @testing.for_all_dtypes() + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes(no_int8=True) @testing.numpy_cupy_allclose() def test_transposed_tensordot(self, xp, dtype): a = testing.shaped_arange((2, 3, 4), xp, dtype).transpose(1, 0, 2) @@ -516,13 +521,15 @@ def test_matrix_power_1(self, xp, dtype): a = testing.shaped_arange((3, 3), xp, dtype) return xp.linalg.matrix_power(a, 1) - @testing.for_all_dtypes() + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes(no_int8=True) @testing.numpy_cupy_allclose() def test_matrix_power_2(self, xp, dtype): a = testing.shaped_arange((3, 3), xp, dtype) return xp.linalg.matrix_power(a, 2) - @testing.for_all_dtypes() + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes(no_int8=True) @testing.numpy_cupy_allclose() def test_matrix_power_3(self, xp, dtype): a = testing.shaped_arange((3, 3), xp, dtype) diff --git a/dpnp/tests/third_party/cupy/logic_tests/test_comparison.py b/dpnp/tests/third_party/cupy/logic_tests/test_comparison.py index 7e56ed5b64b..5215191987b 100644 --- a/dpnp/tests/third_party/cupy/logic_tests/test_comparison.py +++ b/dpnp/tests/third_party/cupy/logic_tests/test_comparison.py @@ -242,7 +242,8 @@ def test_allclose_array_scalar(self, xp, dtype): class TestIsclose(unittest.TestCase): - @testing.for_all_dtypes(no_complex=True) + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes(no_complex=True, no_int8=True) @testing.numpy_cupy_array_equal() def test_is_close_finite(self, xp, dtype): # In numpy<1.10 this test fails when dtype is bool diff --git a/dpnp/tests/third_party/cupy/math_tests/test_matmul.py b/dpnp/tests/third_party/cupy/math_tests/test_matmul.py index 35852d25dbe..fd15ba33110 100644 --- a/dpnp/tests/third_party/cupy/math_tests/test_matmul.py +++ b/dpnp/tests/third_party/cupy/math_tests/test_matmul.py @@ -60,8 +60,9 @@ ) class TestMatmul(unittest.TestCase): - @testing.for_all_dtypes(name="dtype1") - @testing.for_all_dtypes(name="dtype2") + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes(name="dtype1", no_int8=True) + @testing.for_all_dtypes(name="dtype2", no_int8=True) @testing.numpy_cupy_allclose( rtol=1e-3, atol=1e-3, type_check=has_support_aspect64() ) # required for uint8 @@ -70,8 +71,9 @@ def test_operator_matmul(self, xp, dtype1, dtype2): x2 = testing.shaped_arange(self.shape_pair[1], xp, dtype2) return operator.matmul(x1, x2) - @testing.for_all_dtypes(name="dtype1") - @testing.for_all_dtypes(name="dtype2") + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes(name="dtype1", no_int8=True) + @testing.for_all_dtypes(name="dtype2", no_int8=True) @testing.numpy_cupy_allclose( rtol=1e-3, atol=1e-3, type_check=has_support_aspect64() ) # required for uint8 @@ -97,8 +99,9 @@ def test_cupy_matmul(self, xp, dtype1, dtype2): ) class TestMatmulOut(unittest.TestCase): - @testing.for_all_dtypes(name="dtype1") - @testing.for_all_dtypes(name="dtype2") + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes(name="dtype1", no_int8=True) + @testing.for_all_dtypes(name="dtype2", no_int8=True) @testing.numpy_cupy_allclose( rtol=1e-3, atol=1e-3, accept_error=TypeError # required for uint8 ) @@ -140,7 +143,8 @@ def test_overlap_both(self, xp, dtype, shape): class TestMatmulStrides: - @testing.for_all_dtypes() + # no_int8=True is added to avoid overflow + @testing.for_all_dtypes(no_int8=True) @testing.numpy_cupy_allclose(rtol=1e-3, atol=1e-3) # required for uint8 def test_relaxed_c_contiguous_input(self, xp, dtype): x1 = testing.shaped_arange((2, 2, 3), xp, dtype)[:, None, :, :] @@ -171,6 +175,7 @@ class TestMatmulLarge(unittest.TestCase): # Avoid overflow skip_dtypes = { + (numpy.int8, numpy.int8), (numpy.int8, numpy.uint8), (numpy.int8, numpy.int16), (numpy.int8, numpy.float16), diff --git a/dpnp/tests/third_party/cupy/math_tests/test_misc.py b/dpnp/tests/third_party/cupy/math_tests/test_misc.py index c2d7d5ed0c8..2664e249600 100644 --- a/dpnp/tests/third_party/cupy/math_tests/test_misc.py +++ b/dpnp/tests/third_party/cupy/math_tests/test_misc.py @@ -176,7 +176,8 @@ def test_sqrt(self): self.check_unary("sqrt") @testing.for_all_dtypes(no_complex=True) - @testing.numpy_cupy_allclose(atol=1e-5, type_check=has_support_aspect64()) + # atol=1e-3 is needed for int8 + @testing.numpy_cupy_allclose(atol=1e-3, type_check=has_support_aspect64()) def test_cbrt(self, xp, dtype): a = testing.shaped_arange((2, 3, 4), xp, dtype) return xp.cbrt(a) diff --git a/dpnp/tests/third_party/cupy/math_tests/test_trigonometric.py b/dpnp/tests/third_party/cupy/math_tests/test_trigonometric.py index e0d4f484082..3579ddb7fe3 100644 --- a/dpnp/tests/third_party/cupy/math_tests/test_trigonometric.py +++ b/dpnp/tests/third_party/cupy/math_tests/test_trigonometric.py @@ -7,7 +7,9 @@ class TestTrigonometric(unittest.TestCase): @testing.for_all_dtypes(no_complex=True) - @testing.numpy_cupy_allclose(atol=1e-5, type_check=has_support_aspect64()) + @testing.numpy_cupy_allclose( + atol=1e-4, rtol=0.001, type_check=has_support_aspect64() + ) def check_unary(self, name, xp, dtype): a = testing.shaped_arange((2, 3), xp, dtype) return getattr(xp, name)(a) diff --git a/dpnp/tests/third_party/cupy/random_tests/test_permutations.py b/dpnp/tests/third_party/cupy/random_tests/test_permutations.py index eed47320e51..f580ffcca4d 100644 --- a/dpnp/tests/third_party/cupy/random_tests/test_permutations.py +++ b/dpnp/tests/third_party/cupy/random_tests/test_permutations.py @@ -38,6 +38,11 @@ def test_permutation_zero_dim(self): @testing.for_all_dtypes(no_float16=True, no_bool=True, no_complex=True) def test_permutation_sort_1dim(self, dtype): + flag = cupy.issubdtype(dtype, cupy.unsignedinteger) + if flag or dtype in [cupy.int8, cupy.int16]: + pytest.skip( + "dpnp.random.permutation() does not support new integer dtypes." + ) cupy_random = self._xp_random(cupy) a = cupy.arange(10, dtype=dtype) b = cupy.copy(a) @@ -47,6 +52,11 @@ def test_permutation_sort_1dim(self, dtype): @testing.for_all_dtypes(no_float16=True, no_bool=True, no_complex=True) def test_permutation_sort_ndim(self, dtype): + flag = cupy.issubdtype(dtype, cupy.unsignedinteger) + if flag or dtype in [cupy.int8, cupy.int16]: + pytest.skip( + "dpnp.random.permutation() does not support new integer dtypes." + ) cupy_random = self._xp_random(cupy) a = cupy.arange(15, dtype=dtype).reshape(5, 3) b = cupy.copy(a) @@ -58,6 +68,11 @@ def test_permutation_sort_ndim(self, dtype): @testing.for_all_dtypes() def test_permutation_seed1(self, dtype): + flag = cupy.issubdtype(dtype, cupy.unsignedinteger) + if flag or dtype in [cupy.int8, cupy.int16]: + pytest.skip( + "dpnp.random.permutation() does not support new integer dtypes." + ) a = testing.shaped_random((10,), cupy, dtype) b = cupy.copy(a) @@ -89,6 +104,11 @@ def test_shuffle_zero_dim(self): @testing.for_all_dtypes(no_float16=True, no_bool=True, no_complex=True) def test_shuffle_sort_1dim(self, dtype): + flag = cupy.issubdtype(dtype, cupy.unsignedinteger) + if flag or dtype in [cupy.int8, cupy.int16]: + pytest.skip( + "dpnp.random.shuffle() does not support new integer dtypes." + ) a = cupy.arange(10, dtype=dtype) b = cupy.copy(a) cupy.random.shuffle(a) @@ -96,6 +116,11 @@ def test_shuffle_sort_1dim(self, dtype): @testing.for_all_dtypes(no_float16=True, no_bool=True, no_complex=True) def test_shuffle_sort_ndim(self, dtype): + flag = cupy.issubdtype(dtype, cupy.unsignedinteger) + if flag or dtype in [cupy.int8, cupy.int16]: + pytest.skip( + "dpnp.random.shuffle() does not support new integer dtypes." + ) a = cupy.arange(15, dtype=dtype).reshape(5, 3) b = cupy.copy(a) cupy.random.shuffle(a) @@ -105,6 +130,11 @@ def test_shuffle_sort_ndim(self, dtype): @testing.for_all_dtypes() def test_shuffle_seed1(self, dtype): + flag = cupy.issubdtype(dtype, cupy.unsignedinteger) + if flag or dtype in [cupy.int8, cupy.int16]: + pytest.skip( + "dpnp.random.shuffle() does not support new integer dtypes." + ) a = testing.shaped_random((10,), cupy, dtype) b = cupy.copy(a) cupy.random.seed(0) diff --git a/dpnp/tests/third_party/cupy/sorting_tests/test_sort.py b/dpnp/tests/third_party/cupy/sorting_tests/test_sort.py index dc619d77f78..7e791f6a7c0 100644 --- a/dpnp/tests/third_party/cupy/sorting_tests/test_sort.py +++ b/dpnp/tests/third_party/cupy/sorting_tests/test_sort.py @@ -478,6 +478,9 @@ def test_partition_zero_dim(self): @testing.for_all_dtypes() @testing.numpy_cupy_equal() def test_partition_one_dim(self, xp, dtype): + flag = xp.issubdtype(dtype, xp.unsignedinteger) + if flag or dtype in [xp.int8, xp.int16]: + pytest.skip("dpnp.partition() does not support new integer dtypes.") a = testing.shaped_random((self.length,), xp, dtype) kth = 2 x = self.partition(a, kth) diff --git a/dpnp/tests/third_party/cupy/testing/_loops.py b/dpnp/tests/third_party/cupy/testing/_loops.py index 603ec22b1a2..718c3910b64 100644 --- a/dpnp/tests/third_party/cupy/testing/_loops.py +++ b/dpnp/tests/third_party/cupy/testing/_loops.py @@ -251,7 +251,7 @@ def _make_positive_masks(impl, args, kw, name, sp_name, scipy_name): assert error is None if not isinstance(result, (tuple, list)): result = (result,) - return [cupy.asnumpy(r) >= 0 for r in result] + return [r >= 0 for r in result] def _contains_signed_and_unsigned(kw): @@ -411,8 +411,8 @@ def test_func(*args, **kw): if cupy_r.shape == (): skip = (mask == 0).all() else: - cupy_r = cupy_r[mask].get() - numpy_r = numpy_r[mask] + cupy_r = cupy_r[mask] + numpy_r = numpy_r[mask.asnumpy()] if not skip: check_func(cupy_r, numpy_r) @@ -1082,21 +1082,43 @@ def _get_int_bool_dtypes(): _complex_dtypes = _get_supported_complex_dtypes() _regular_float_dtypes = _get_supported_float_dtypes() -_float_dtypes = _regular_float_dtypes -_signed_dtypes = () -_unsigned_dtypes = tuple(numpy.dtype(i).type for i in "BHILQ") -_int_dtypes = _signed_dtypes + _unsigned_dtypes -_int_bool_dtypes = _int_dtypes +_float_dtypes = _get_float_dtypes() +_signed_dtypes = _get_signed_dtypes() +_unsigned_dtypes = _get_unsigned_dtypes() +_int_dtypes = _get_int_dtypes() +_int_bool_dtypes = _get_int_bool_dtypes() _regular_dtypes = _regular_float_dtypes + _int_bool_dtypes _dtypes = _float_dtypes + _int_bool_dtypes -def _make_all_dtypes(no_float16, no_bool, no_complex): - return (numpy.int64, numpy.int32) + _get_supported_float_dtypes() +def _make_all_dtypes(no_float16, no_bool, no_complex, no_int8): + if no_float16: + dtypes = _regular_float_dtypes + else: + dtypes = _float_dtypes + + if no_bool: + dtypes += _int_dtypes + else: + dtypes += _int_bool_dtypes + + if no_int8: + dtypes = tuple( + filter(lambda dt: dt not in [numpy.int8, numpy.uint8], dtypes) + ) + + if config.complex_types and not no_complex: + dtypes += _complex_dtypes + + return dtypes def for_all_dtypes( - name="dtype", no_float16=False, no_bool=False, no_complex=False + name="dtype", + no_float16=False, + no_bool=False, + no_complex=False, + no_int8=False, ): """Decorator that checks the fixture with all dtypes. @@ -1108,6 +1130,9 @@ def for_all_dtypes( omitted from candidate dtypes. no_complex(bool): If ``True``, ``numpy.complex64`` and ``numpy.complex128`` are omitted from candidate dtypes. + no_int8(bool): If ``True``, ``numpy.int8`` and + ``numpy.uint8`` are omitted from candidate dtypes. + This option is generally used to avoid overflow. dtypes to be tested: ``numpy.complex64`` (optional), ``numpy.complex128`` (optional), @@ -1151,7 +1176,7 @@ def for_all_dtypes( .. seealso:: :func:`cupy.testing.for_dtypes` """ return for_dtypes( - _make_all_dtypes(no_float16, no_bool, no_complex), name=name + _make_all_dtypes(no_float16, no_bool, no_complex, no_int8), name=name ) @@ -1321,6 +1346,7 @@ def for_all_dtypes_combination( no_bool=False, full=None, no_complex=False, + no_int8=False, ): """Decorator that checks the fixture with a product set of all dtypes. @@ -1334,12 +1360,15 @@ def for_all_dtypes_combination( will be tested. Otherwise, the subset of combinations will be tested (see description in :func:`cupy.testing.for_dtypes_combination`). - no_complex(bool): If, True, ``numpy.complex64`` and + no_complex(bool): If, ``True``, ``numpy.complex64`` and ``numpy.complex128`` are omitted from candidate dtypes. + no_int8(bool): If, ``True``, ``numpy.int8`` and + ``numpy.uint8`` are omitted from candidate dtypes. + This option is generally used to avoid overflow. .. seealso:: :func:`cupy.testing.for_dtypes_combination` """ - types = _make_all_dtypes(no_float16, no_bool, no_complex) + types = _make_all_dtypes(no_float16, no_bool, no_complex, no_int8) return for_dtypes_combination(types, names, full)