From a09891060a1b190e5928abcdf09b5c5a22e22c9a Mon Sep 17 00:00:00 2001 From: Alexander Kalistratov Date: Wed, 9 Oct 2024 05:02:17 +0200 Subject: [PATCH 1/9] Add integer dtypes (int8,int16, uint8-uint64) to dpnp interface Add missing aliases to integer types: [u]byte, ushort, [u]longlong Not adding [u]long aliases as it is removed from NumPy (https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations) Removed int alias as it is depricate in NumPy Extend tests types matrix by these types Add environment variable DPNP_TEST_ALL_TYPES to enable/disable these types in tests Failing dpnp tests: test_arraycreation.py::test_geomspace test_arraycreation.py::test_linspace test_arraycreation.py::test_logspace test_fft.py::TestFft2::test_fft2 test_fft.py::TestRfft2::test_rfft2 test_histogram.py::TestDigitize::test_digitize test_indexing.py::TestPut::test_input_1d test_indexing.py::TestPut::test_input_2d test_indexing.py::TestPutAlongAxis::test_replace_max test_indexing.py::TestTake::test_1d test_indexing.py::TestTake::test_2d test_indexing.py::TestTakeAlongAxis::test_broadcast test_indexing.py::TestTakeAlongAxis::test_empty test_indexing.py::TestTakeAlongAxis::test_empty test_indexing.py::TestTakeAlongAxis::test_multi_dimensions test_linalg.py::TestCond::test_cond test_linalg.py::TestEigenvalue::test_eigenvalues test_linalg.py::TestLstsq::test_lstsq_diff_type test_linalg.py::TestNorm::test_norm_1D test_linalg.py::TestNorm::test_norm_2D test_linalg.py::TestNorm::test_norm_ND test_linalg.py::TestNorm::test_norm_usm_ndarray test_linalg.py::TestPinv::test_pinv test_linalg.py::TestQr::test_qr test_linalg.py::TestSvd::test_svd test_manipulation.py::TestUnique::test_2d_axis_signed_inetger test_manipulation.py::test_copyto_dtype test_mathematical.py::TestAngle::test_angle test_mathematical.py::TestCumLogSumExp::test_basic test_mathematical.py::TestCumProd::test_out_dtype test_mathematical.py::TestCumSum::test_out_dtype test_mathematical.py::TestFix::test_basic test_mathematical.py::TestFix::test_out test_mathematical.py::TestHypot::test_hypot test_mathematical.py::TestLogSumExp::test_logsumexp test_mathematical.py::TestLogSumExp::test_logsumexp_dtype test_mathematical.py::TestLogSumExp::test_logsumexp_out test_mathematical.py::TestLogSumExp::test_logsumexp_out_dtype test_mathematical.py::TestMathematical::test_remainder test_mathematical.py::TestMatmul::test_matmul_axes_ND_ND test_mathematical.py::TestMatmul::test_matmul_axes_out test_mathematical.py::TestMatmul::test_matmul_dtype test_mathematical.py::TestMatmul::test_matmul_dtype_matrix_inout test_mathematical.py::TestMatmul::test_matmul_dtype_matrix_inputs test_mathematical.py::TestMatmul::test_matmul_out1 test_mathematical.py::TestMatmul::test_matmul_out2 test_mathematical.py::TestPower::test_basic test_mathematical.py::TestProd::test_prod_out_dtype test_mathematical.py::TestReduceHypot::test_reduce_hypot test_mathematical.py::TestReduceHypot::test_reduce_hypot_dtype test_mathematical.py::TestReduceHypot::test_reduce_hypot_out test_mathematical.py::TestUnwrap::test_discont test_mathematical.py::TestUnwrap::test_rand_period test_nanfunctions.py::TestNanProd::test_nanprod_out_dtype test_product.py::TestDot::test_dot test_product.py::TestDot::test_dot_ndarray test_product.py::TestDot::test_dot_out test_product.py::TestDot::test_dot_out_scalar test_product.py::TestDot::test_dot_scalar test_product.py::TestInner::test_inner test_product.py::TestInner::test_inner_scalar test_product.py::TestKron::test_kron_scalar test_product.py::TestMultiDot::test_multi_dot test_product.py::TestMultiDot::test_multi_dot_all_2d test_product.py::TestMultiDot::test_multi_dot_out test_product.py::TestTensordot::test_tensordot test_product.py::TestTensordot::test_tensordot_axes test_product.py::TestTensordot::test_tensordot_input_dtype_matrix test_product.py::TestTensordot::test_tensordot_scalar test_sort.py::test_partition test_statistics.py::TestAverage::test_avg test_statistics.py::TestAverage::test_avg_strided test_statistics.py::TestStd::test_std_strided test_statistics.py::TestVar::test_var_strided test_statistics.py::test_median test_strides.py::test_cumlogsumexp test_strides.py::test_logsumexp test_strides.py::test_reduce_hypot test_strides.py::test_strides_erf test_sum.py::test_sum test_umath.py::TestArctan2::test_arctan2 test_umath.py::TestCbrt::test_cbrt test_umath.py::TestCopySign::test_copysign test_umath.py::TestFloatPower::test_negative_base_value_complex_dtype test_umath.py::TestLogAddExp::test_logaddexp test_umath.py::TestRsqrt::test_rsqrt test_umath.py::TestUmath::test_out --- .github/workflows/conda-package.yml | 219 +++++++++++++++++- doc/reference/dtypes_table.rst | 15 +- dpnp/dpnp_iface_types.py | 32 ++- dpnp/tests/config.py | 6 + dpnp/tests/helper.py | 34 ++- dpnp/tests/test_absolute.py | 4 +- dpnp/tests/test_arraycreation.py | 7 +- dpnp/tests/test_arraypad.py | 30 ++- dpnp/tests/test_linalg.py | 20 +- dpnp/tests/test_random_state.py | 22 +- .../cupy/random_tests/test_distributions.py | 6 +- dpnp/tests/third_party/cupy/testing/_loops.py | 70 +++++- 12 files changed, 415 insertions(+), 50 deletions(-) create mode 100644 dpnp/tests/config.py diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 136863e85d38..8ff31e7205e3 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -159,7 +159,7 @@ jobs: echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV - name: Install dpnp - run: mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} + run: mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest pytest-xdist python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} env: TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.CHANNELS }}' MAMBA_NO_LOW_SPEED_LIMIT: 1 @@ -175,7 +175,7 @@ jobs: - name: Run tests if: env.RERUN_TESTS_ON_FAILURE != 'true' run: | - python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests - name: Run tests if: env.RERUN_TESTS_ON_FAILURE == 'true' @@ -190,7 +190,91 @@ jobs: . $CONDA/etc/profile.d/mamba.sh mamba activate ${{ env.TEST_ENV_NAME }} - python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + + test_linux_all_dtypes: + name: Test ['ubuntu-latest', python='${{ matrix.python }}'] + + needs: build + + runs-on: ubuntu-latest + + defaults: + run: + shell: bash -el {0} + + strategy: + matrix: + python: ['3.12'] + + continue-on-error: true + + env: + channel-path: '${{ github.workspace }}/channel/' + pkg-path-in-channel: '${{ github.workspace }}/channel/linux-64/' + extracted-pkg-path: '${{ github.workspace }}/pkg/' + ver-json-path: '${{ github.workspace }}/version.json' + + steps: + - name: Download artifact + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + with: + name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }} + path: ${{ env.pkg-path-in-channel }} + + - name: Extract package archive + run: | + mkdir -p ${{ env.extracted-pkg-path }} + tar -xvf ${{ env.pkg-path-in-channel }}/${{ env.PACKAGE_NAME }}-*.tar.bz2 -C ${{ env.extracted-pkg-path }} + + - name: Setup miniconda + uses: conda-incubator/setup-miniconda@d2e6a045a86077fb6cad6f5adf368e9076ddaa8d # v3.1.0 + with: + miniforge-version: latest + use-mamba: 'true' + channels: conda-forge + conda-remove-defaults: 'true' + python-version: ${{ matrix.python }} + activate-environment: ${{ env.TEST_ENV_NAME }} + + - name: Install conda-index + run: mamba install conda-index=${{ env.CONDA_INDEX_VERSION }} + + - name: Create conda channel + run: | + python -m conda_index ${{ env.channel-path }} + + - name: Test conda channel + run: | + mamba 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 + run: | + export PACKAGE_VERSION=$(python -c "${{ env.VER_SCRIPT1 }} ${{ env.VER_SCRIPT2 }}") + + echo PACKAGE_VERSION=${PACKAGE_VERSION} + echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV + + - name: Install dpnp + run: mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest pytest-xdist python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} + env: + TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.CHANNELS }}' + MAMBA_NO_LOW_SPEED_LIMIT: 1 + + - name: List installed packages + run: mamba list + + - name: Smoke test + run: | + python -c "import dpnp, dpctl; dpctl.lsplatform()" + python -c "import dpnp; print(dpnp.__version__)" + + - name: Run full tests + env: + DPNP_TEST_ALL_INT_TYPES: 1 + run: | + pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests test_windows: name: Test ['windows-2019', python='${{ matrix.python }}'] @@ -282,7 +366,7 @@ jobs: - name: Install dpnp run: | @echo on - mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} + mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest pytest-xdist python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} env: TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.CHANNELS }}' MAMBA_NO_LOW_SPEED_LIMIT: 1 @@ -311,7 +395,7 @@ jobs: - name: Run tests if: env.RERUN_TESTS_ON_FAILURE != 'true' run: | - pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests - name: Run tests if: env.RERUN_TESTS_ON_FAILURE == 'true' @@ -322,7 +406,130 @@ jobs: max_attempts: ${{ env.RUN_TESTS_MAX_ATTEMPTS }} retry_on: any command: | - python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + + test_windows_all_dtypes: + name: Test ['windows-2019', python='${{ matrix.python }}'] + + needs: build + + runs-on: windows-2019 + + defaults: + run: + shell: cmd /C CALL {0} + + strategy: + matrix: + python: ['3.12'] + + continue-on-error: true + + env: + channel-path: '${{ github.workspace }}\channel\' + pkg-path-in-channel: '${{ github.workspace }}\channel\win-64\' + extracted-pkg-path: '${{ github.workspace }}\pkg' + ver-json-path: '${{ github.workspace }}\version.json' + workdir: '${{ github.workspace }}' + + steps: + - name: Download artifact + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + with: + name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }} + path: ${{ env.pkg-path-in-channel }} + + - name: Extract package archive + run: | + @echo on + mkdir -p ${{ env.extracted-pkg-path }} + + set SEARCH_SCRIPT="DIR ${{ env.pkg-path-in-channel }} /s/b | FINDSTR /r "dpnp-.*\.tar\.bz2"" + FOR /F "tokens=* USEBACKQ" %%F IN (`%SEARCH_SCRIPT%`) DO ( + SET FULL_PACKAGE_PATH=%%F + ) + echo FULL_PACKAGE_PATH: %FULL_PACKAGE_PATH% + + python -c "import shutil; shutil.unpack_archive(r\"%FULL_PACKAGE_PATH%\", extract_dir=r\"${{ env.extracted-pkg-path }}\")" + dir ${{ env.extracted-pkg-path }} + + - name: Setup miniconda + uses: conda-incubator/setup-miniconda@d2e6a045a86077fb6cad6f5adf368e9076ddaa8d # v3.1.0 + with: + miniforge-version: latest + use-mamba: 'true' + channels: conda-forge + conda-remove-defaults: 'true' + python-version: ${{ matrix.python }} + activate-environment: ${{ env.TEST_ENV_NAME }} + + - name: Store conda paths as envs + run: | + @echo on + (echo CONDA_LIB_PATH=%CONDA_PREFIX%\Library\lib\) >> %GITHUB_ENV% + (echo CONDA_LIB_BIN_PATH=%CONDA_PREFIX%\Library\bin\) >> %GITHUB_ENV% + + - name: Install conda-index + run: mamba install conda-index=${{ env.CONDA_INDEX_VERSION }} + + - name: Create conda channel + run: | + @echo on + python -m conda_index ${{ env.channel-path }} + + - name: Test conda channel + run: | + @echo on + mamba 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 }} + + - name: Get package version + run: | + @echo on + set "SCRIPT=${{ env.VER_SCRIPT1 }} ${{ env.VER_SCRIPT2 }}" + FOR /F "tokens=* USEBACKQ" %%F IN (`python -c "%SCRIPT%"`) DO ( + set PACKAGE_VERSION=%%F + ) + echo PACKAGE_VERSION: %PACKAGE_VERSION% + (echo PACKAGE_VERSION=%PACKAGE_VERSION%) >> %GITHUB_ENV% + + - name: Install dpnp + run: | + @echo on + mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest pytest-xdist python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} + env: + TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.CHANNELS }}' + MAMBA_NO_LOW_SPEED_LIMIT: 1 + + - name: List installed packages + run: mamba list + + - name: Activate OCL CPU RT + shell: pwsh + run: | + $script_path="$env:CONDA_PREFIX\Scripts\set-intel-ocl-icd-registry.ps1" + if (Test-Path $script_path) { + &$script_path + } else { + Write-Warning "File $script_path was NOT found!" + } + # Check the variable assisting OpenCL CPU driver to find TBB DLLs which are not located where it expects them by default + $cl_cfg="$env:CONDA_PREFIX\Library\lib\cl.cfg" + Get-Content -Tail 5 -Path $cl_cfg + + - name: Smoke test + run: | + python -c "import dpnp, dpctl; dpctl.lsplatform()" + python -c "import dpnp; print(dpnp.__version__)" + + - name: Run full tests + if: matrix.python == '3.12' + env: + DPNP_TEST_ALL_INT_TYPES: 1 + run: | + pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests upload: name: Upload ['${{ matrix.os }}', python='${{ matrix.python }}'] diff --git a/doc/reference/dtypes_table.rst b/doc/reference/dtypes_table.rst index 6d851da401ad..40cf3d742b3c 100644 --- a/doc/reference/dtypes_table.rst +++ b/doc/reference/dtypes_table.rst @@ -13,22 +13,35 @@ Table below shows a list of all supported data types (dtypes) and constants of t - Constants * - - :obj:`bool ` + - :obj:`int8 ` + - :obj:`int16 ` - :obj:`int32 ` - :obj:`int64 ` + - :obj:`uint8 ` + - :obj:`uint16 ` + - :obj:`uint32 ` + - :obj:`uint64 ` - :obj:`float32 ` - :obj:`float64 ` - :obj:`complex64 ` - :obj:`complex128 ` - - :obj:`bool_ ` + - :obj:`byte ` - :obj:`cdouble ` - :obj:`csingle ` - :obj:`double ` - :obj:`float16 ` - - :obj:`int ` - :obj:`int_ ` - :obj:`intc ` + - :obj:`intp ` + - :obj:`longlong ` - :obj:`single ` + - :obj:`ubyte ` + - :obj:`uintc ` + - :obj:`uintp ` + - :obj:`ushort ` + - :obj:`ulonglong ` - - :obj:`e ` - :obj:`euler_gamma ` diff --git a/dpnp/dpnp_iface_types.py b/dpnp/dpnp_iface_types.py index 9fbe5b377c10..e06ed5c122e0 100644 --- a/dpnp/dpnp_iface_types.py +++ b/dpnp/dpnp_iface_types.py @@ -40,6 +40,7 @@ __all__ = [ "bool", "bool_", + "byte", "cdouble", "complex128", "complex64", @@ -57,8 +58,9 @@ "iinfo", "inexact", "inf", - "int", "int_", + "int8", + "int16", "int32", "int64", "integer", @@ -66,12 +68,24 @@ "intp", "issubdtype", "is_type_supported", + "longlong", "nan", "newaxis", "number", "pi", + "short", "signedinteger", "single", + "ubyte", + "uint8", + "uint16", + "uint32", + "uint64", + "uintc", + "uintp", + "unsignedinteger", + "ushort", + "ulonglong", ] @@ -81,6 +95,7 @@ # ============================================================================= bool = numpy.bool_ bool_ = numpy.bool_ +byte = numpy.byte cdouble = numpy.cdouble complex128 = numpy.complex128 complex64 = numpy.complex64 @@ -93,16 +108,29 @@ float64 = numpy.float64 floating = numpy.floating inexact = numpy.inexact -int = numpy.int_ int_ = numpy.int_ +int8 = numpy.int8 +int16 = numpy.int16 int32 = numpy.int32 int64 = numpy.int64 integer = numpy.integer intc = numpy.intc intp = numpy.intp +longlong = numpy.longlong number = numpy.number +short = numpy.short signedinteger = numpy.signedinteger single = numpy.single +ubyte = numpy.ubyte +uint8 = numpy.uint8 +uint16 = numpy.uint16 +uint32 = numpy.uint32 +uint64 = numpy.uint64 +uintc = numpy.uintc +uintp = numpy.uintp +unsignedinteger = numpy.unsignedinteger +ushort = numpy.ushort +ulonglong = numpy.ulonglong # ============================================================================= diff --git a/dpnp/tests/config.py b/dpnp/tests/config.py new file mode 100644 index 000000000000..0069efe23ee7 --- /dev/null +++ b/dpnp/tests/config.py @@ -0,0 +1,6 @@ +import os + +all_int_types = int(os.getenv("DPNP_TEST_ALL_INT_TYPES", 0)) +float16_types = int(os.getenv("DPNP_TEST_FLOAT_16", 0)) +complex_types = int(os.getenv("DPNP_TEST_COMPLEX_TYPES", 0)) +bool_types = int(os.getenv("DPNP_TEST_BOOL_TYPES", 0)) diff --git a/dpnp/tests/helper.py b/dpnp/tests/helper.py index ee457670f591..44945dc4c8b4 100644 --- a/dpnp/tests/helper.py +++ b/dpnp/tests/helper.py @@ -2,9 +2,11 @@ import dpctl import numpy +import pytest from numpy.testing import assert_allclose, assert_array_equal import dpnp +from dpnp.tests import config def assert_dtype_allclose( @@ -88,6 +90,18 @@ def get_integer_dtypes(): Build a list of integer types supported by DPNP. """ + if config.all_int_types: + return [ + dpnp.int8, + dpnp.int16, + dpnp.int32, + dpnp.int64, + dpnp.uint8, + dpnp.uint16, + dpnp.uint32, + dpnp.uint64, + ] + return [dpnp.int32, dpnp.int64] @@ -134,7 +148,13 @@ def get_float_complex_dtypes(no_float16=True, device=None): def get_all_dtypes( - no_bool=False, no_float16=True, no_complex=False, no_none=False, device=None + no_bool=False, + no_float16=True, + no_complex=False, + no_none=False, + device=None, + xfail_dtypes=None, + exclude=None, ): """ Build a list of types supported by DPNP based on input flags and device capabilities. @@ -158,6 +178,18 @@ def get_all_dtypes( # add None value to validate a default dtype if not no_none: dtypes.append(None) + + def mark_xfail(dtype): + if xfail_dtypes is not None and dtype in xfail_dtypes: + return pytest.param(dtype, marks=pytest.mark.xfail) + return dtype + + def not_excluded(dtype): + if exclude is None: + return True + return dtype not in exclude + + dtypes = [mark_xfail(dtype) for dtype in dtypes if not_excluded(dtype)] return dtypes diff --git a/dpnp/tests/test_absolute.py b/dpnp/tests/test_absolute.py index 1c6a42e98c64..3f5c4860f242 100644 --- a/dpnp/tests/test_absolute.py +++ b/dpnp/tests/test_absolute.py @@ -13,9 +13,9 @@ @pytest.mark.parametrize("func", ["abs", "absolute"]) -@pytest.mark.parametrize("dtype", get_all_dtypes()) +@pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) def test_abs(func, dtype): - a = numpy.array([1, 0, 2, -3, -1, 2, 21, -9], dtype=dtype) + a = numpy.array([1, 0, 2, -3, -1, 2, 21, -9]).astype(dtype=dtype) ia = dpnp.array(a) result = getattr(dpnp, func)(ia) diff --git a/dpnp/tests/test_arraycreation.py b/dpnp/tests/test_arraycreation.py index 909d4d464b06..445c348a95d0 100644 --- a/dpnp/tests/test_arraycreation.py +++ b/dpnp/tests/test_arraycreation.py @@ -708,10 +708,15 @@ def test_dpctl_tensor_input(func, args): ids=["1", "5", "numpy.array(10)", "dpnp.array(17)", "dpt.asarray(100)"], ) @pytest.mark.parametrize( - "dtype", get_all_dtypes(no_bool=True, no_float16=False) + "dtype", + get_all_dtypes(no_bool=True, no_float16=False), ) @pytest.mark.parametrize("retstep", [True, False]) def test_linspace(start, stop, num, dtype, retstep): + if numpy.issubdtype(dtype, numpy.unsignedinteger): + start = abs(start) + stop = abs(stop) + res_np = numpy.linspace(start, stop, num, dtype=dtype, retstep=retstep) res_dp = dpnp.linspace(start, stop, num, dtype=dtype, retstep=retstep) diff --git a/dpnp/tests/test_arraypad.py b/dpnp/tests/test_arraypad.py index 34a71eec7070..16b7c23c75ef 100644 --- a/dpnp/tests/test_arraypad.py +++ b/dpnp/tests/test_arraypad.py @@ -30,7 +30,11 @@ class TestPad: "empty": {}, } - @pytest.mark.parametrize("mode", _all_modes.keys()) + # .keys() returns set which is not ordered + # consistent order is required by xdist plugin + _modes = sorted(_all_modes.keys()) + + @pytest.mark.parametrize("mode", _modes) def test_basic(self, mode): a_np = numpy.arange(100) a_dp = dpnp.array(a_np) @@ -43,7 +47,7 @@ def test_basic(self, mode): else: assert_array_equal(result, expected) - @pytest.mark.parametrize("mode", _all_modes.keys()) + @pytest.mark.parametrize("mode", _modes) def test_memory_layout_persistence(self, mode): """Test if C and F order is preserved for all pad modes.""" x = dpnp.ones((5, 10), order="C") @@ -52,13 +56,13 @@ def test_memory_layout_persistence(self, mode): assert dpnp.pad(x, 5, mode).flags.f_contiguous @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) - @pytest.mark.parametrize("mode", _all_modes.keys()) + @pytest.mark.parametrize("mode", _modes) def test_dtype_persistence(self, dtype, mode): arr = dpnp.zeros((3, 2, 1), dtype=dtype) result = dpnp.pad(arr, 1, mode=mode) assert result.dtype == dtype - @pytest.mark.parametrize("mode", _all_modes.keys()) + @pytest.mark.parametrize("mode", _modes) def test_non_contiguous_array(self, mode): a_np = numpy.arange(24).reshape(4, 6)[::2, ::2] a_dp = dpnp.arange(24).reshape(4, 6)[::2, ::2] @@ -73,12 +77,14 @@ def test_non_contiguous_array(self, mode): # TODO: include "linear_ramp" when dpnp issue gh-2084 is resolved @pytest.mark.parametrize("pad_width", [0, (0, 0), ((0, 0), (0, 0))]) - @pytest.mark.parametrize("mode", _all_modes.keys() - {"linear_ramp"}) + @pytest.mark.parametrize( + "mode", [m for m in _modes if m not in {"linear_ramp"}] + ) def test_zero_pad_width(self, pad_width, mode): arr = dpnp.arange(30).reshape(6, 5) assert_array_equal(arr, dpnp.pad(arr, pad_width, mode=mode)) - @pytest.mark.parametrize("mode", _all_modes.keys()) + @pytest.mark.parametrize("mode", _modes) def test_pad_non_empty_dimension(self, mode): a_np = numpy.ones((2, 0, 2)) a_dp = dpnp.array(a_np) @@ -95,14 +101,14 @@ def test_pad_non_empty_dimension(self, mode): ((3, 4, 5), (0, 1, 2)), ], ) - @pytest.mark.parametrize("mode", _all_modes.keys()) + @pytest.mark.parametrize("mode", _modes) def test_misshaped_pad_width1(self, pad_width, mode): arr = dpnp.arange(30).reshape((6, 5)) match = "operands could not be broadcast together" with pytest.raises(ValueError, match=match): dpnp.pad(arr, pad_width, mode) - @pytest.mark.parametrize("mode", _all_modes.keys()) + @pytest.mark.parametrize("mode", _modes) def test_misshaped_pad_width2(self, mode): arr = dpnp.arange(30).reshape((6, 5)) match = ( @@ -115,7 +121,7 @@ def test_misshaped_pad_width2(self, mode): @pytest.mark.parametrize( "pad_width", [-2, (-2,), (3, -1), ((5, 2), (-2, 3)), ((-4,), (2,))] ) - @pytest.mark.parametrize("mode", _all_modes.keys()) + @pytest.mark.parametrize("mode", _modes) def test_negative_pad_width(self, pad_width, mode): arr = dpnp.arange(30).reshape((6, 5)) match = "index can't contain negative values" @@ -126,14 +132,14 @@ def test_negative_pad_width(self, pad_width, mode): "pad_width", ["3", "word", None, 3.4, complex(1, -1), ((-2.1, 3), (3, 2))], ) - @pytest.mark.parametrize("mode", _all_modes.keys()) + @pytest.mark.parametrize("mode", _modes) def test_bad_type(self, pad_width, mode): arr = dpnp.arange(30).reshape((6, 5)) match = "`pad_width` must be of integral type." with pytest.raises(TypeError, match=match): dpnp.pad(arr, pad_width, mode) - @pytest.mark.parametrize("mode", _all_modes.keys()) + @pytest.mark.parametrize("mode", _modes) def test_kwargs(self, mode): """Test behavior of pad's kwargs for the given mode.""" allowed = self._all_modes[mode] @@ -439,7 +445,7 @@ def test_pad_empty_dim_valid(self, mode): @pytest.mark.parametrize( "mode", - _all_modes.keys() - {"constant", "empty"}, + [m for m in _modes if m not in {"constant", "empty"}], ) def test_pad_empty_dim_invalid(self, mode): match = ( diff --git a/dpnp/tests/test_linalg.py b/dpnp/tests/test_linalg.py index 810258d3f3f9..f239adae84fe 100644 --- a/dpnp/tests/test_linalg.py +++ b/dpnp/tests/test_linalg.py @@ -2124,7 +2124,9 @@ 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()) + @pytest.mark.parametrize( + "dtype", get_all_dtypes(xfail_dtypes=[dpnp.uint64]) + ) @pytest.mark.parametrize( "ord", [None, -dpnp.inf, -2, -1, 0, 1, 2, 3.5, dpnp.inf] ) @@ -2139,7 +2141,9 @@ 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()) + @pytest.mark.parametrize( + "dtype", get_all_dtypes(xfail_dtypes=[dpnp.uint64]) + ) @pytest.mark.parametrize( "ord", [None, -dpnp.inf, -2, -1, 1, 2, 3, dpnp.inf, "fro", "nuc"] ) @@ -2164,7 +2168,12 @@ def test_2D(self, dtype, ord, axis, keepdims): assert_dtype_allclose(result, expected) @pytest.mark.usefixtures("suppress_divide_numpy_warnings") - @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) + @pytest.mark.parametrize( + "dtype", + get_all_dtypes( + no_none=True, xfail_dtypes=[dpnp.uint16, dpnp.uint32, dpnp.uint64] + ), + ) @pytest.mark.parametrize( "ord", [None, -dpnp.inf, -2, -1, 1, 2, 3, dpnp.inf, "fro", "nuc"] ) @@ -2195,7 +2204,10 @@ 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()) + @pytest.mark.parametrize( + "dtype", + get_all_dtypes(xfail_dtypes=[dpnp.uint16, dpnp.uint32, dpnp.uint64]), + ) @pytest.mark.parametrize( "ord", [None, -dpnp.inf, -2, -1, 1, 2, 3, dpnp.inf, "fro", "nuc"] ) diff --git a/dpnp/tests/test_random_state.py b/dpnp/tests/test_random_state.py index 7107a919c4e0..35ff4154cde5 100644 --- a/dpnp/tests/test_random_state.py +++ b/dpnp/tests/test_random_state.py @@ -241,7 +241,7 @@ def test_fallback(self, loc, scale): float, dpnp.int64, dpnp.int32, - dpnp.int, + dpnp.int_, int, numpy.clongdouble, dpnp.complex128, @@ -254,7 +254,7 @@ def test_fallback(self, loc, scale): "float", "dpnp.int64", "dpnp.int32", - "dpnp.int", + "dpnp.int_", "int", "numpy.clongdouble", "dpnp.complex128", @@ -364,8 +364,8 @@ def test_wrong_dims(self): class TestRandInt: @pytest.mark.parametrize( "dtype", - [int, dpnp.int32, dpnp.int], - ids=["int", "dpnp.int32", "dpnp.int"], + [int, dpnp.int32, dpnp.int_], + ids=["int", "dpnp.int32", "dpnp.int_"], ) @pytest.mark.parametrize( "usm_type", @@ -377,7 +377,7 @@ def test_distr(self, dtype, usm_type): low = 1 high = 10 - if dtype == dpnp.int and dtype != dpnp.dtype("int32"): + if dtype == dpnp.int_ and dtype != dpnp.dtype("int32"): pytest.skip( "dtype isn't alias on dpnp.int32 on the target OS, so there will be a fallback" ) @@ -564,10 +564,10 @@ def test_bounds_fallback(self, low, high): @pytest.mark.usefixtures("allow_fall_back_on_numpy") @pytest.mark.parametrize( "dtype", - [dpnp.int64, dpnp.int, dpnp.bool, dpnp.bool_, bool], + [dpnp.int64, dpnp.int_, dpnp.bool, dpnp.bool_, bool], ids=[ "dpnp.int64", - "dpnp.int", + "dpnp.int_", "dpnp.bool", "dpnp.bool_", "bool", @@ -579,7 +579,7 @@ def test_dtype_fallback(self, dtype): high = 37 if not dtype in {dpnp.bool_, bool} else 2 size = (3, 2, 5) - if dtype == dpnp.int and dtype == dpnp.dtype("int32"): + if dtype == dpnp.int_ and dtype == dpnp.dtype("int32"): pytest.skip( "dtype is alias on dpnp.int32 on the target OS, so no fallback here" ) @@ -1155,7 +1155,7 @@ def test_fallback(self, low, high): dpnp.float16, float, dpnp.int64, - dpnp.int, + dpnp.int_, int, numpy.clongdouble, dpnp.complex128, @@ -1167,7 +1167,7 @@ def test_fallback(self, low, high): "dpnp.float16", "float", "dpnp.int64", - "dpnp.int", + "dpnp.int_", "int", "numpy.clongdouble", "dpnp.complex128", @@ -1177,7 +1177,7 @@ def test_fallback(self, low, high): ], ) def test_invalid_dtype(self, dtype): - if dtype == dpnp.int and dtype == dpnp.dtype("int32"): + if dtype == dpnp.int_ and dtype == dpnp.dtype("int32"): pytest.skip( "dtype is alias on dpnp.int32 on the target OS, so no error here" ) diff --git a/dpnp/tests/third_party/cupy/random_tests/test_distributions.py b/dpnp/tests/third_party/cupy/random_tests/test_distributions.py index 16ad014645aa..ebed860fd294 100644 --- a/dpnp/tests/third_party/cupy/random_tests/test_distributions.py +++ b/dpnp/tests/third_party/cupy/random_tests/test_distributions.py @@ -22,7 +22,7 @@ def check_distribution(self, dist_name, params, dtype=None): np_out = numpy.asarray( getattr(numpy.random, dist_name)(size=self.shape, **params), dtype ) - dt_kward = {dtype: dtype} if dtype else {} + dt_kward = {"dtype": dtype} if dtype else {} cp_out = getattr(_distributions, dist_name)( size=self.shape, **dt_kward, **cp_params ) @@ -72,12 +72,14 @@ def test_beta(self, a_dtype, b_dtype): "shape": [(4, 3, 2), (3, 2)], "n_shape": [(), (3, 2)], "p_shape": [(), (3, 2)], - "dtype": _int_dtypes, # to escape timeout + # "dtype": _int_dtypes, # to escape timeout + "dtype": [None], # no dtype supported } ) ) class TestDistributionsBinomial(RandomDistributionsTestCase): + @pytest.mark.skip("n and p params as arrays are not supported") @testing.for_signed_dtypes("n_dtype") @testing.for_float_dtypes("p_dtype") def test_binomial(self, n_dtype, p_dtype): diff --git a/dpnp/tests/third_party/cupy/testing/_loops.py b/dpnp/tests/third_party/cupy/testing/_loops.py index 901d1111b0be..e9a0fde71044 100644 --- a/dpnp/tests/third_party/cupy/testing/_loops.py +++ b/dpnp/tests/third_party/cupy/testing/_loops.py @@ -8,10 +8,12 @@ from typing import Tuple, Type import numpy +import pytest from dpctl import select_default_device from dpctl.tensor._numpy_helper import AxisError import dpnp as cupy +from dpnp.tests import config from dpnp.tests.third_party.cupy.testing import _array, _parameterized from dpnp.tests.third_party.cupy.testing._pytest_impl import is_available @@ -978,7 +980,7 @@ def test_func(*args, **kw): return decorator -def for_dtypes(dtypes, name="dtype"): +def for_dtypes(dtypes, name="dtype", xfail_dtypes=None): """Decorator for parameterized dtype test. Args: @@ -1009,7 +1011,11 @@ def test_func(*args, **kw): try: kw[name] = numpy.dtype(dtype).type - impl(*args, **kw) + if xfail_dtypes is not None and dtype in xfail_dtypes: + impl_ = pytest.mark.xfail(impl) + else: + impl_ = impl + impl_(*args, **kw) except _skip_classes as e: print("skipped: {} = {} ({})".format(name, dtype, e)) except Exception: @@ -1039,19 +1045,67 @@ def _get_supported_complex_dtypes(): return (numpy.complex64,) +def _get_int_dtypes(): + if config.all_int_types: + return _signed_dtypes + _unsigned_dtypes + else: + return (numpy.int64, numpy.int32) + + +def _get_float_dtypes(): + if config.float16_types: + return _regular_float_dtypes + (numpy.float16,) + else: + return _regular_float_dtypes + + +def _get_signed_dtypes(): + if config.all_int_types: + return tuple(numpy.dtype(i).type for i in "bhilq") + else: + return (numpy.int32,) + + +def _get_unsigned_dtypes(): + if config.all_int_types: + return tuple(numpy.dtype(i).type for i in "BHILQ") + else: + return (numpy.uint32,) + + +def _get_int_bool_dtypes(): + if config.bool_types: + return _int_dtypes + (numpy.bool_,) + else: + return _int_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() + 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 def for_all_dtypes( From 9c2875047584178663bc9fd864eac11036d412c4 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad <120411540+vtavana@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:00:03 -0600 Subject: [PATCH 2/9] update tests for newly added integr dtypes (int8, int16, uint8-uint64) (#2233) In this PR, 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/2230. --- .github/workflows/conda-package.yml | 18 +- dpnp/backend/kernels/dpnp_krnl_common.cpp | 2 +- .../kernels/elementwise_functions/i0.hpp | 2 +- dpnp/dpnp_algo/dpnp_elementwise_common.py | 11 +- dpnp/dpnp_iface_linearalgebra.py | 32 ++- dpnp/dpnp_iface_manipulation.py | 13 + dpnp/dpnp_iface_nanfunctions.py | 4 +- dpnp/fft/dpnp_utils_fft.py | 5 +- dpnp/tests/helper.py | 55 ++-- dpnp/tests/test_amin_amax.py | 32 +-- dpnp/tests/test_arraycreation.py | 23 +- dpnp/tests/test_bitwise.py | 3 +- dpnp/tests/test_fft.py | 18 +- dpnp/tests/test_histogram.py | 29 +- dpnp/tests/test_indexing.py | 209 +++++++------- dpnp/tests/test_linalg.py | 26 +- dpnp/tests/test_manipulation.py | 6 +- dpnp/tests/test_mathematical.py | 264 +++++++++++------- dpnp/tests/test_nanfunctions.py | 9 +- dpnp/tests/test_ndarray.py | 7 +- dpnp/tests/test_outer.py | 6 +- dpnp/tests/test_product.py | 83 +++--- dpnp/tests/test_sort.py | 9 +- dpnp/tests/test_strides.py | 33 ++- dpnp/tests/test_sum.py | 23 +- dpnp/tests/test_sycl_queue.py | 1 + dpnp/tests/test_umath.py | 27 +- 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 | 32 ++- 42 files changed, 702 insertions(+), 451 deletions(-) diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 8ff31e7205e3..c1b6d797875c 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 @@ -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: | @@ -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 @@ -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 }}'] @@ -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 @@ -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 }} @@ -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 @@ -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/backend/kernels/dpnp_krnl_common.cpp b/dpnp/backend/kernels/dpnp_krnl_common.cpp index 0c25716a236f..22f50986c2c1 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 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 ddb81d88cbc9..68bc41ea377f 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 20241208L #endif #if __SYCL_COMPILER_VERSION >= __SYCL_COMPILER_BESSEL_I0_SUPPORT diff --git a/dpnp/dpnp_algo/dpnp_elementwise_common.py b/dpnp/dpnp_algo/dpnp_elementwise_common.py index 6cb603fb4804..71cd1ba5a18a 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_linearalgebra.py b/dpnp/dpnp_iface_linearalgebra.py index bb89f0769d97..588679b34689 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,20 @@ ] +# 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) + 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") + + def dot(a, b, out=None): """ Dot product of `a` and `b`. @@ -137,8 +153,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 +642,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 +720,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 +1056,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 +1119,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_manipulation.py b/dpnp/dpnp_iface_manipulation.py index 401b7c67a7f4..e53b3bf92438 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/dpnp_iface_nanfunctions.py b/dpnp/dpnp_iface_nanfunctions.py index a808617469fc..950e86b9d511 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 e2855acd60cd..43d46763f50b 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 == 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 44945dc4c8b4..1ffa208227c1 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): @@ -147,17 +142,25 @@ 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, 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 +169,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)) @@ -194,7 +197,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. @@ -210,6 +219,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`` @@ -226,7 +238,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: @@ -239,10 +251,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) @@ -256,6 +271,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_amin_amax.py b/dpnp/tests/test_amin_amax.py index 1b119ab225b4..35f45cd40822 100644 --- a/dpnp/tests/test_amin_amax.py +++ b/dpnp/tests/test_amin_amax.py @@ -4,21 +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]], - ], - dtype=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)): @@ -28,20 +26,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 +57,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 445c348a95d0..1b4d97de6241 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,16 +173,18 @@ 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) ) 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 +700,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 +849,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 41f10c023543..33e327218d45 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 8915daa43e21..33f81a7394d8 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 @@ -816,7 +815,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"]) @@ -934,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) @@ -999,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_histogram.py b/dpnp/tests/test_histogram.py index 6a4e8abceb6e..3a87fc2402f2 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,7 +45,12 @@ class TestDigitize: ], ) def test_digitize(self, x, bins, dtype, right): - x = x.astype(dtype) + x = get_abs_array(x, dtype) + 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) @@ -527,18 +533,27 @@ 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): + # discussed in numpy issue 17760 + 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 61b91015461b..02c6ff15a499 100644 --- a/dpnp/tests/test_indexing.py +++ b/dpnp/tests/test_indexing.py @@ -17,7 +17,14 @@ 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, + is_win_platform, + numpy_version, +) from .third_party.cupy import testing @@ -43,12 +50,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 +129,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): - a = numpy.array([-2, -1, 0, 1, 2, 3], dtype=a_dt) - cond = numpy.array([1, -1, 2, 0, -2, 3], 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) @@ -132,7 +139,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): - a = numpy.array([-2, -1, 0, 1, 2, 3], 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) @@ -165,7 +172,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 +392,7 @@ 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) + a = get_abs_array([1, 0, 2, -1, 0, 0, 8], dtype) ia = dpnp.array(a) np_res = numpy.nonzero(a) @@ -437,22 +444,22 @@ 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) + a = get_abs_array([-2, -1, 0, 1, 2], a_dt) b = numpy.copy(a) ia = dpnp.array(a) ib = dpnp.array(b) - 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) @@ -465,6 +472,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 +494,30 @@ 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): + a = get_abs_array([[-1, 0, 1], [-2, -3, -4], [2, 3, 4]], a_dt) ia = dpnp.array(a) + vals = [10, 20] - ind = numpy.array(indices, dtype=ind_dt) + ind = get_abs_array(indices, 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 +555,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 +567,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 +598,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 +613,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 +655,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,18 +688,27 @@ 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) - 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"): 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, both NumPy and dpnp work properly + # 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) + assert_array_equal(result, expected) else: assert_raises(TypeError, ia.take, iind, mode=mode) assert_raises(TypeError, a.take, ind, mode=mode) @@ -706,28 +716,34 @@ 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) - 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) - 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): + 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) - expected = dpnp.array([-2, 2], dtype=a.dtype) + expected = get_abs_array([-2, 2], a_dt) assert_array_equal(result, expected) @pytest.mark.parametrize("xp", [numpy, dpnp]) @@ -887,7 +903,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 +952,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 +960,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 +978,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 +1082,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 +1109,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 f239adae84fe..990ab59b1730 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) @@ -2124,9 +2123,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 +2138,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 +2165,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 +2197,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 97c951ad1562..52c307eaa573 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 756367c4bcb4..737b3c4d63f4 100644 --- a/dpnp/tests/test_mathematical.py +++ b/dpnp/tests/test_mathematical.py @@ -19,10 +19,12 @@ import dpnp from dpnp.dpnp_array import dpnp_array +from dpnp.dpnp_utils import map_dtype_to_device from .helper import ( assert_dtype_allclose, generate_random_numpy_array, + get_abs_array, get_all_dtypes, get_complex_dtypes, get_float_complex_dtypes, @@ -30,6 +32,7 @@ get_integer_dtypes, has_support_aspect16, has_support_aspect64, + numpy_version, ) from .test_umath import ( _get_numpy_arrays_1in_1out, @@ -39,8 +42,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() @@ -56,7 +59,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() @@ -64,10 +66,11 @@ 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 + 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()) - @pytest.mark.parametrize("deg", [True, False]) def test_angle_complex(self, dtype, deg): a = numpy.random.rand(10) b = numpy.random.rand(10) @@ -258,7 +261,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 +315,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 +397,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 +501,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 +875,7 @@ 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 - ) + 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) @@ -889,15 +893,12 @@ 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 + 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) - 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 +1296,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): - a = numpy.array([-1.5, 0, 2.0], dtype=a_dt) - b = numpy.array([-0, 0.5, 1.0], 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) @@ -1350,7 +1351,10 @@ def test_1d(self, dt): result = dpnp.i0(ia) expected = numpy.i0(a) - assert_dtype_allclose(result, expected) + # NumPy promotes result of integer inputs to float64, but dpnp + # follows Type Promotion Rules + 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()) def test_2d(self, dt): @@ -1405,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 ): @@ -1415,9 +1419,18 @@ 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 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) + 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 +1906,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 +1930,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 +2026,16 @@ 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 + 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]) @@ -2036,7 +2053,10 @@ 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 + 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") @@ -2111,7 +2131,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 @@ -2151,7 +2171,7 @@ def test_fp16(self): @pytest.mark.parametrize("dt", get_integer_dtypes()) def test_integer(self, dt): - a = numpy.array([1, 0, -3], dtype=dt) + a = get_abs_array([1, 0, -3], dt) ia = dpnp.array(a) result = dpnp.spacing(ia) @@ -2174,7 +2194,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 @@ -2308,27 +2328,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 +2367,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,10 +2496,12 @@ 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) + dpnp_a = dpnp.array(np_a) result = dpnp.negative(dpnp_a) expected = numpy.negative(np_a) @@ -2504,8 +2533,8 @@ def test_negative_boolean(): ) @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) @@ -2581,7 +2610,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 +2641,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) @@ -2719,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 @@ -2822,7 +2852,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 +3185,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 +3202,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 +3229,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 +3243,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 +3270,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 +3287,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 +3314,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 +3401,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 +3743,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 +3812,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 +3864,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 +3893,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 +4107,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 +4132,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 +4160,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 5645586219e4..a8eccc81c879 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, @@ -586,7 +587,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) @@ -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_ndarray.py b/dpnp/tests/test_ndarray.py index 153b3d0c2e9e..3d3c3ee8b633 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,7 +24,7 @@ ids=["[-2, -1, 0, 1, 2]", "[[-2, -1], [1, 2]]", "[]"], ) def test_astype(arr, arr_dtype, res_dtype): - 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) @@ -43,8 +44,8 @@ def test_astype_subok_error(): ids=["[-2, -1, 0, 1, 2]", "[[-2, -1], [1, 2]]", "[]"], ) def test_flatten(arr, arr_dtype): - 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_outer.py b/dpnp/tests/test_outer.py index 77f57ebf7ddc..bcdc8091ed05 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 95c643a6494c..762d2dbb992b 100644 --- a/dpnp/tests/test_product.py +++ b/dpnp/tests/test_product.py @@ -5,28 +5,19 @@ from numpy.testing import assert_raises import dpnp +from dpnp.dpnp_utils import map_dtype_to_device from .helper import ( assert_dtype_allclose, generate_random_numpy_array, get_all_dtypes, get_complex_dtypes, + is_win_platform, + numpy_version, ) 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 +212,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 +247,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 +279,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 +318,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 +370,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 +438,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 +456,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 +506,14 @@ 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 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)) @pytest.mark.parametrize( @@ -611,7 +610,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 +630,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 +654,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 +674,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 +761,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 +791,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 +803,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 +895,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 0a4fdfec5280..665ab8bee450 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 0f6732ab9a44..beacf6109fab 100644 --- a/dpnp/tests/test_strides.py +++ b/dpnp/tests/test_strides.py @@ -161,7 +161,10 @@ 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 + 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)) @@ -171,7 +174,10 @@ 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 + 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,15 +187,24 @@ 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 + 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)) -@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 21ecab42a6af..54a998bfa3a6 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,13 @@ (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, order) a = dpnp.asarray(a_np) if transpose: @@ -53,9 +51,18 @@ 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_) + and numpy.issubdtype(dtype_in, numpy.signedinteger) + and not a_np.sum(axis=axis).all() + ): + # 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: + dpnp_res = a.sum(axis=axis, dtype=dtype_out, keepdims=keepdims) 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_sycl_queue.py b/dpnp/tests/test_sycl_queue.py index 9da87c3db865..ba584504d4d3 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_umath.py b/dpnp/tests/test_umath.py index 65b7908b09f5..46ab9681e5d0 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, @@ -180,8 +181,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 +326,7 @@ 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) + a = get_abs_array([numpy.pi, -0.5 * numpy.pi], dtype) ia = dpnp.array(a) result = dpnp.degrees(ia) @@ -356,7 +365,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 +376,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 +473,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 +522,7 @@ 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) + a = get_abs_array([120.0, -90.0], dtype) ia = dpnp.array(a) result = dpnp.radians(ia) @@ -712,6 +726,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/test_usm_type.py b/dpnp/tests/test_usm_type.py index e8e97d2ea385..5231c136cdf9 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 2d268e53b37b..729468948209 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 282c38b72e66..3acebaaeb3ad 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 515243d89c5c..eaf01d1b345c 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 b0d209e2570d..06b4ef8dc75a 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 a977b44bbdbd..213edf0b2c0e 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 0714fbc05a72..bb44b791d413 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 a712c1cb0328..2617e100a9c2 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 7e56ed5b64bf..5215191987b4 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 35852d25dbe7..fd15ba33110a 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 c2d7d5ed0c86..2664e2496000 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 e0d4f484082d..3579ddb7fe37 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 eed47320e51b..f580ffcca4d7 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 dc619d77f786..7e791f6a7c0e 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 e9a0fde71044..718c3910b64c 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) @@ -1091,7 +1091,7 @@ def _get_int_bool_dtypes(): _dtypes = _float_dtypes + _int_bool_dtypes -def _make_all_dtypes(no_float16, no_bool, no_complex): +def _make_all_dtypes(no_float16, no_bool, no_complex, no_int8): if no_float16: dtypes = _regular_float_dtypes else: @@ -1102,6 +1102,11 @@ def _make_all_dtypes(no_float16, no_bool, no_complex): 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 @@ -1109,7 +1114,11 @@ def _make_all_dtypes(no_float16, no_bool, no_complex): 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. @@ -1121,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), @@ -1164,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 ) @@ -1334,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. @@ -1347,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) From d0870b15c54cc288bc5097ac26afdd667f8032fd Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Fri, 24 Jan 2025 07:15:45 -0800 Subject: [PATCH 3/9] update newly added tests for elemnt-wise in-place operators --- dpnp/tests/test_binary_ufuncs.py | 85 ++++++++++++++++++++++--------- dpnp/tests/test_bitwise.py | 78 +++++++++++++++++++++------- dpnp/tests/test_dtype_routines.py | 3 +- 3 files changed, 123 insertions(+), 43 deletions(-) diff --git a/dpnp/tests/test_binary_ufuncs.py b/dpnp/tests/test_binary_ufuncs.py index 397e1811593b..492f56287ebb 100644 --- a/dpnp/tests/test_binary_ufuncs.py +++ b/dpnp/tests/test_binary_ufuncs.py @@ -75,11 +75,19 @@ def test_inplace_strides(self, dtype): @pytest.mark.parametrize("dtype1", ALL_DTYPES) @pytest.mark.parametrize("dtype2", ALL_DTYPES) def test_inplace_dtype(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, -2, 0, 1, 0], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, -2, 0, 1, 0], dtype=dtype2) ia, ib = dpnp.array(a), dpnp.array(b) - if numpy.can_cast(dtype2, dtype1, casting="same_kind"): + if numpy.issubdtype(dtype1, numpy.signedinteger) and numpy.issubdtype( + dtype2, numpy.uint64 + ): + # For this special case, NumPy raises an error but dpnp works + b = b.astype(numpy.int64) + a += b + ia += ib + assert_dtype_allclose(ia, a) + elif numpy.can_cast(dtype2, dtype1, casting="same_kind"): a += b ia += ib assert_dtype_allclose(ia, a) @@ -93,17 +101,24 @@ def test_inplace_dtype(self, dtype1, dtype2): @pytest.mark.parametrize("dtype1", ALL_DTYPES) @pytest.mark.parametrize("dtype2", ALL_DTYPES) def test_inplace_dtype_explicit(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, -2, 0, 1, 0], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, -2, 0, 1, 0], dtype=dtype2) ia, ib = dpnp.array(a), dpnp.array(b) - if numpy.can_cast(dtype2, dtype1, casting="same_kind"): + if numpy.issubdtype(dtype1, numpy.signedinteger) and numpy.issubdtype( + dtype2, numpy.uint64 + ): + # For this special case, NumPy raises an error but dpnp works + result = dpnp.add(ia, ib, out=ia) + expected = numpy.add(a, b.astype(numpy.int64), out=a) + assert_dtype_allclose(result, expected) + elif numpy.can_cast(dtype2, dtype1, casting="same_kind"): result = dpnp.add(ia, ib, out=ia) expected = numpy.add(a, b, out=a) assert_dtype_allclose(result, expected) else: assert_raises(TypeError, numpy.add, a, b, out=a) - assert_raises(ValueError, dpnp.add, ia, ib, out=ia) + # assert_raises(ValueError, dpnp.add, ia, ib, out=ia) @pytest.mark.parametrize("shape", [(0,), (15,), (2, 2)]) def test_invalid_shape(self, shape): @@ -235,8 +250,8 @@ def test_inplace_strides(self, dtype): @pytest.mark.parametrize("dtype1", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("dtype2", get_float_complex_dtypes()) def test_inplace_dtype(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, -2, -10, 1, 10], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, -2, -10, 1, 10], dtype=dtype2) ia, ib = dpnp.array(a), dpnp.array(b) if numpy.can_cast(dtype2, dtype1, casting="same_kind"): @@ -253,8 +268,8 @@ def test_inplace_dtype(self, dtype1, dtype2): @pytest.mark.parametrize("dtype1", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("dtype2", get_float_complex_dtypes()) def test_inplace_dtype_explicit(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, -2, -10, 1, 10], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, -2, -10, 1, 10], dtype=dtype2) ia, ib = dpnp.array(a), dpnp.array(b) if numpy.can_cast(dtype2, dtype1, casting="same_kind"): @@ -340,8 +355,8 @@ def test_inplace_scalar(self, func, dtype): @pytest.mark.parametrize("dtype1", [dpnp.bool] + ALL_DTYPES) @pytest.mark.parametrize("dtype2", get_float_dtypes()) def test_inplace_dtype(self, func, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, -2, -10, 1, 10], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, -2, -10, 1, 10], dtype=dtype2) ia, ib = dpnp.array(a), dpnp.array(b) if numpy.can_cast(dtype2, dtype1, casting="same_kind"): @@ -613,11 +628,19 @@ def test_inplace_strides(self, dtype): @pytest.mark.parametrize("dtype1", ALL_DTYPES) @pytest.mark.parametrize("dtype2", ALL_DTYPES) def test_inplace_dtype(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, -2, 0, 1, 0], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, -2, 0, 1, 0], dtype=dtype2) ia, ib = dpnp.array(a), dpnp.array(b) - if numpy.can_cast(dtype2, dtype1, casting="same_kind"): + if numpy.issubdtype(dtype1, numpy.signedinteger) and numpy.issubdtype( + dtype2, numpy.uint64 + ): + # For this special case, NumPy raises an error but dpnp works + b = b.astype(numpy.int64) + a *= b + ia *= ib + assert_dtype_allclose(ia, a) + elif numpy.can_cast(dtype2, dtype1, casting="same_kind"): a *= b ia *= ib assert_dtype_allclose(ia, a) @@ -855,11 +878,19 @@ def test_inplace_strided_out(self, dtype): @pytest.mark.parametrize("dtype1", ALL_DTYPES) @pytest.mark.parametrize("dtype2", ALL_DTYPES) def test_inplace_dtype(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, 2, 0, 1, 3], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, 2, 0, 1, 3], dtype=dtype2) ia, ib = dpnp.array(a), dpnp.array(b) - if numpy.can_cast(dtype2, dtype1, casting="same_kind") and not ( + if numpy.issubdtype(dtype1, numpy.signedinteger) and numpy.issubdtype( + dtype2, numpy.uint64 + ): + # For this special case, NumPy raises an error but dpnp works + b = b.astype(numpy.int64) + a **= b + ia **= ib + assert_dtype_allclose(ia, a) + elif numpy.can_cast(dtype2, dtype1, casting="same_kind") and not ( dtype1 == dtype2 == dpnp.bool ): a **= b @@ -904,7 +935,7 @@ def test_integer_power_of_0_or_1(self, val, dtype): assert_equal(func(ia), func(a)) - @pytest.mark.parametrize("dtype", get_integer_dtypes()) + @pytest.mark.parametrize("dtype", get_integer_dtypes(no_unsigned=True)) def test_integer_to_negative_power(self, dtype): a = dpnp.arange(2, 10, dtype=dtype) b = dpnp.full(8, -2, dtype=dtype) @@ -1062,11 +1093,19 @@ def test_inplace_strides(self, dtype): @pytest.mark.parametrize("dtype1", ALL_DTYPES) @pytest.mark.parametrize("dtype2", ALL_DTYPES) def test_inplace_dtype(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, -2, 0, 1, 0], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, -2, 0, 1, 0], dtype=dtype2) ia, ib = dpnp.array(a), dpnp.array(b) - if numpy.can_cast(dtype2, dtype1, casting="same_kind"): + if numpy.issubdtype(dtype1, numpy.signedinteger) and numpy.issubdtype( + dtype2, numpy.uint64 + ): + # For this special case, NumPy raises an error but dpnp works + b = b.astype(numpy.int64) + a -= b + ia -= ib + assert_dtype_allclose(ia, a) + elif numpy.can_cast(dtype2, dtype1, casting="same_kind"): a -= b ia -= ib assert_dtype_allclose(ia, a) diff --git a/dpnp/tests/test_bitwise.py b/dpnp/tests/test_bitwise.py index 95b0fe11f225..d41a4900c8e3 100644 --- a/dpnp/tests/test_bitwise.py +++ b/dpnp/tests/test_bitwise.py @@ -4,7 +4,7 @@ import dpnp as inp -from .helper import assert_dtype_allclose, get_integer_dtypes +from .helper import assert_dtype_allclose, get_abs_array, get_integer_dtypes @pytest.mark.parametrize( @@ -32,6 +32,8 @@ def array_or_scalar(xp, data, dtype=None): return numpy.dtype(dtype).type(data) return data + if numpy.issubdtype(dtype, numpy.unsignedinteger): + data = xp.abs(xp.array(data)) return xp.array(data, dtype=dtype) def _test_unary_int(self, name, data, dtype): @@ -182,15 +184,23 @@ def test_invert_out(dtype): @pytest.mark.parametrize("dtype2", [inp.bool] + get_integer_dtypes()) class TestBitwiseInplace: def test_bitwise_and(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, -2, 0, 1, 0], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, -2, 0, 1, 0], dtype=dtype2) ia, ib = inp.array(a), inp.array(b) a &= True ia &= True assert_array_equal(ia, a) - if numpy.can_cast(dtype2, dtype1, casting="same_kind"): + if numpy.issubdtype(dtype1, numpy.signedinteger) and numpy.issubdtype( + dtype2, numpy.uint64 + ): + # For this special case, NumPy raises an error but dpnp works + b = b.astype(numpy.int64) + a &= b + ia &= ib + assert_array_equal(ia, a) + elif numpy.can_cast(dtype2, dtype1, casting="same_kind"): a &= b ia &= ib assert_array_equal(ia, a) @@ -202,15 +212,23 @@ def test_bitwise_and(self, dtype1, dtype2): ia &= ib def test_bitwise_or(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, -2, 0, 1, 0], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, -2, 0, 1, 0], dtype=dtype2) ia, ib = inp.array(a), inp.array(b) a |= False ia |= False assert_array_equal(ia, a) - if numpy.can_cast(dtype2, dtype1, casting="same_kind"): + if numpy.issubdtype(dtype1, numpy.signedinteger) and numpy.issubdtype( + dtype2, numpy.uint64 + ): + # For this special case, NumPy raises an error but dpnp works + b = b.astype(numpy.int64) + a |= b + ia |= ib + assert_array_equal(ia, a) + elif numpy.can_cast(dtype2, dtype1, casting="same_kind"): a |= b ia |= ib assert_array_equal(ia, a) @@ -222,18 +240,26 @@ def test_bitwise_or(self, dtype1, dtype2): ia |= ib def test_bitwise_xor(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, -2, 0, 1, 0], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, -2, 0, 1, 0], dtype=dtype2) ia, ib = inp.array(a), inp.array(b) a ^= False ia ^= False assert_array_equal(ia, a) - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, -2, 0, 1, 0], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, -2, 0, 1, 0], dtype=dtype2) ia, ib = inp.array(a), inp.array(b) - if numpy.can_cast(dtype2, dtype1, casting="same_kind"): + if numpy.issubdtype(dtype1, numpy.signedinteger) and numpy.issubdtype( + dtype2, numpy.uint64 + ): + # For this special case, NumPy raises an error but dpnp works + b = b.astype(numpy.int64) + a ^= b + ia ^= ib + assert_array_equal(ia, a) + elif numpy.can_cast(dtype2, dtype1, casting="same_kind"): a ^= b ia ^= ib assert_array_equal(ia, a) @@ -249,15 +275,23 @@ def test_bitwise_xor(self, dtype1, dtype2): @pytest.mark.parametrize("dtype2", get_integer_dtypes()) class TestBitwiseShiftInplace: def test_bitwise_left_shift(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, 2, 0, 1, 0], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, 2, 0, 1, 0], dtype=dtype2) ia, ib = inp.array(a), inp.array(b) a <<= True ia <<= True assert_array_equal(ia, a) - if numpy.can_cast(dtype2, dtype1, casting="same_kind"): + if numpy.issubdtype(dtype1, numpy.signedinteger) and numpy.issubdtype( + dtype2, numpy.uint64 + ): + # For this special case, NumPy raises an error but dpnp works + b = b.astype(numpy.int64) + a <<= b + ia <<= ib + assert_array_equal(ia, a) + elif numpy.can_cast(dtype2, dtype1, casting="same_kind"): a <<= b ia <<= ib assert_array_equal(ia, a) @@ -269,15 +303,23 @@ def test_bitwise_left_shift(self, dtype1, dtype2): ia <<= ib def test_bitwise_right_shift(self, dtype1, dtype2): - a = numpy.array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) - b = numpy.array([5, 2, 0, 1, 0], dtype=dtype2) + a = get_abs_array([[-7, 6, -3, 2, -1], [0, -3, 4, 5, -6]], dtype=dtype1) + b = get_abs_array([5, 2, 0, 1, 0], dtype=dtype2) ia, ib = inp.array(a), inp.array(b) a >>= True ia >>= True assert_array_equal(ia, a) - if numpy.can_cast(dtype2, dtype1, casting="same_kind"): + if numpy.issubdtype(dtype1, numpy.signedinteger) and numpy.issubdtype( + dtype2, numpy.uint64 + ): + # For this special case, NumPy raises an error but dpnp works + b = b.astype(numpy.int64) + a >>= b + ia >>= ib + assert_array_equal(ia, a) + elif numpy.can_cast(dtype2, dtype1, casting="same_kind"): a >>= b ia >>= ib assert_array_equal(ia, a) diff --git a/dpnp/tests/test_dtype_routines.py b/dpnp/tests/test_dtype_routines.py index 8fab16c70936..21c42bbf89ba 100644 --- a/dpnp/tests/test_dtype_routines.py +++ b/dpnp/tests/test_dtype_routines.py @@ -30,9 +30,8 @@ class TestIsDType: @pytest.mark.parametrize( "dt, close_dt", [ - # TODO: replace with (dpnp.uint64, dpnp.uint32) once available (dpnp.int64, dpnp.int32), - (numpy.uint64, numpy.uint32), + (dpnp.uint64, dpnp.uint32), (dpnp.float64, dpnp.float32), (dpnp.complex128, dpnp.complex64), ], From 56db2059a1914f9d4db9f459ba08ab04a8b343b5 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Fri, 24 Jan 2025 07:18:00 -0800 Subject: [PATCH 4/9] remove debugging leftover --- dpnp/tests/test_binary_ufuncs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpnp/tests/test_binary_ufuncs.py b/dpnp/tests/test_binary_ufuncs.py index 492f56287ebb..5bf64684e6fe 100644 --- a/dpnp/tests/test_binary_ufuncs.py +++ b/dpnp/tests/test_binary_ufuncs.py @@ -118,7 +118,7 @@ def test_inplace_dtype_explicit(self, dtype1, dtype2): assert_dtype_allclose(result, expected) else: assert_raises(TypeError, numpy.add, a, b, out=a) - # assert_raises(ValueError, dpnp.add, ia, ib, out=ia) + assert_raises(ValueError, dpnp.add, ia, ib, out=ia) @pytest.mark.parametrize("shape", [(0,), (15,), (2, 2)]) def test_invalid_shape(self, shape): From 191688b5c0f46ba3192ae7f1cb795f4072b2b9ff Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Tue, 28 Jan 2025 07:19:24 -0800 Subject: [PATCH 5/9] update TODOs in test_array_api_info.py --- dpnp/tests/test_array_api_info.py | 38 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/dpnp/tests/test_array_api_info.py b/dpnp/tests/test_array_api_info.py index ef30b19eca49..c3c8d687b030 100644 --- a/dpnp/tests/test_array_api_info.py +++ b/dpnp/tests/test_array_api_info.py @@ -56,14 +56,14 @@ def test_dtypes_all(): assert dtypes == ( { "bool": dpnp.bool_, - "int8": numpy.int8, # TODO: replace with dpnp.int8 - "int16": numpy.int16, # TODO: replace with dpnp.int16 + "int8": dpnp.int8, + "int16": dpnp.int16, "int32": dpnp.int32, "int64": dpnp.int64, - "uint8": numpy.uint8, # TODO: replace with dpnp.uint8 - "uint16": numpy.uint16, # TODO: replace with dpnp.uint16 - "uint32": numpy.uint32, # TODO: replace with dpnp.uint32 - "uint64": numpy.uint64, # TODO: replace with dpnp.uint64 + "uint8": dpnp.uint8, + "uint16": dpnp.uint16, + "uint32": dpnp.uint32, + "uint64": dpnp.uint64, "float32": dpnp.float32, } | ({"float64": dpnp.float64} if has_support_aspect64() else {}) @@ -75,16 +75,16 @@ def test_dtypes_all(): dtype_categories = { "bool": {"bool": dpnp.bool_}, "signed integer": { - "int8": numpy.int8, # TODO: replace with dpnp.int8 - "int16": numpy.int16, # TODO: replace with dpnp.int16 + "int8": dpnp.int8, + "int16": dpnp.int16, "int32": dpnp.int32, "int64": dpnp.int64, }, - "unsigned integer": { # TODO: replace with dpnp dtypes once available - "uint8": numpy.uint8, - "uint16": numpy.uint16, - "uint32": numpy.uint32, - "uint64": numpy.uint64, + "unsigned integer": { + "uint8": dpnp.uint8, + "uint16": dpnp.uint16, + "uint32": dpnp.uint32, + "uint64": dpnp.uint64, }, "integral": ("signed integer", "unsigned integer"), "real floating": {"float32": dpnp.float32} @@ -108,14 +108,14 @@ def test_dtypes_tuple(): dtypes = info.dtypes(kind=("bool", "integral")) assert dtypes == { "bool": dpnp.bool_, - "int8": numpy.int8, # TODO: replace with dpnp.int8 - "int16": numpy.int16, # TODO: replace with dpnp.int16 + "int8": dpnp.int8, + "int16": dpnp.int16, "int32": dpnp.int32, "int64": dpnp.int64, - "uint8": numpy.uint8, # TODO: replace with dpnp.uint8 - "uint16": numpy.uint16, # TODO: replace with dpnp.uint16 - "uint32": numpy.uint32, # TODO: replace with dpnp.uint32 - "uint64": numpy.uint64, # TODO: replace with dpnp.uint64 + "uint8": dpnp.uint8, + "uint16": dpnp.uint16, + "uint32": dpnp.uint32, + "uint64": dpnp.uint64, } From 43fb4cd8ac829234003f2c93ceb093d58f4d7a73 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Tue, 28 Jan 2025 09:33:01 -0800 Subject: [PATCH 6/9] update yaml file --- .github/workflows/conda-package.yml | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 99cf25ed99bf..66e39ce210fa 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -248,7 +248,6 @@ jobs: env: channel-path: '${{ github.workspace }}/channel/' pkg-path-in-channel: '${{ github.workspace }}/channel/linux-64/' - extracted-pkg-path: '${{ github.workspace }}/pkg/' ver-json-path: '${{ github.workspace }}/version.json' steps: @@ -258,15 +257,10 @@ jobs: name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }} path: ${{ env.pkg-path-in-channel }} - - name: Extract package archive - run: | - mkdir -p ${{ env.extracted-pkg-path }} - tar -xvf ${{ env.pkg-path-in-channel }}/${{ env.PACKAGE_NAME }}-*.tar.bz2 -C ${{ env.extracted-pkg-path }} - - name: Setup miniconda id: setup_miniconda continue-on-error: true - uses: conda-incubator/setup-miniconda@d2e6a045a86077fb6cad6f5adf368e9076ddaa8d # v3.1.0 + uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3.1.1 with: miniforge-version: latest use-mamba: 'true' @@ -277,7 +271,7 @@ jobs: - name: ReSetup miniconda if: steps.setup_miniconda.outcome == 'failure' - uses: conda-incubator/setup-miniconda@d2e6a045a86077fb6cad6f5adf368e9076ddaa8d # v3.1.0 + uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3.1.1 with: miniforge-version: latest use-mamba: 'true' @@ -287,7 +281,8 @@ jobs: activate-environment: ${{ env.TEST_ENV_NAME }} - name: Install conda-index - run: mamba install conda-index=${{ env.CONDA_INDEX_VERSION }} + run: | + mamba install conda-index=${{ env.CONDA_INDEX_VERSION }} - name: Create conda channel run: | @@ -491,7 +486,6 @@ jobs: env: channel-path: '${{ github.workspace }}\channel\' pkg-path-in-channel: '${{ github.workspace }}\channel\win-64\' - extracted-pkg-path: '${{ github.workspace }}\pkg' ver-json-path: '${{ github.workspace }}\version.json' workdir: '${{ github.workspace }}' @@ -502,22 +496,19 @@ jobs: name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }} path: ${{ env.pkg-path-in-channel }} - - name: Extract package archive + - name: Store a path to package archive run: | @echo on - mkdir -p ${{ env.extracted-pkg-path }} - set SEARCH_SCRIPT="DIR ${{ env.pkg-path-in-channel }} /s/b | FINDSTR /r "dpnp-.*\.tar\.bz2"" + set SEARCH_SCRIPT="DIR ${{ env.pkg-path-in-channel }} /s/b | FINDSTR /r "dpnp-.*\.conda"" FOR /F "tokens=* USEBACKQ" %%F IN (`%SEARCH_SCRIPT%`) DO ( SET FULL_PACKAGE_PATH=%%F ) echo FULL_PACKAGE_PATH: %FULL_PACKAGE_PATH% - - python -c "import shutil; shutil.unpack_archive(r\"%FULL_PACKAGE_PATH%\", extract_dir=r\"${{ env.extracted-pkg-path }}\")" - dir ${{ env.extracted-pkg-path }} + (echo FULL_PACKAGE_PATH=%FULL_PACKAGE_PATH%) >> %GITHUB_ENV% - name: Setup miniconda - uses: conda-incubator/setup-miniconda@d2e6a045a86077fb6cad6f5adf368e9076ddaa8d # v3.1.0 + uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3.1.1 with: miniforge-version: latest use-mamba: 'true' @@ -533,7 +524,8 @@ jobs: (echo CONDA_LIB_BIN_PATH=%CONDA_PREFIX%\Library\bin\) >> %GITHUB_ENV% - name: Install conda-index - run: mamba install conda-index=${{ env.CONDA_INDEX_VERSION }} + run: | + mamba install conda-index=${{ env.CONDA_INDEX_VERSION }} - name: Create conda channel run: | From 1c502703ea872de5a10c0df317fc2d45e4eb7fa6 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Tue, 28 Jan 2025 11:16:05 -0800 Subject: [PATCH 7/9] update yaml file --- .github/workflows/conda-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 66e39ce210fa..10d78cd27935 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -329,9 +329,9 @@ jobs: - name: Run tests for all dtypes env: - DPNP_TEST_ALL_INT_TYPES: 1 + DPNP_TEST_ALL_INT_TYPES: 1 run: | - python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests test_windows: name: Test From e90eba978edcf4d3e31a97b2560e6182c26acca5 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Mon, 3 Feb 2025 10:35:11 -0800 Subject: [PATCH 8/9] unmute array-api-test --- .github/workflows/array-api-skips.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/array-api-skips.txt b/.github/workflows/array-api-skips.txt index bfbf71e906d4..bb990cec7200 100644 --- a/.github/workflows/array-api-skips.txt +++ b/.github/workflows/array-api-skips.txt @@ -1,8 +1,5 @@ # array API tests to be skipped -# no 'uint8' dtype -array_api_tests/test_array_object.py::test_getitem_masking - # missing unique-like functions array_api_tests/test_has_names.py::test_has_names[set-unique_all] array_api_tests/test_has_names.py::test_has_names[set-unique_counts] From e01c969b4f3e747f92c2ff5a6dcb330c6bb39fa6 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad <120411540+vtavana@users.noreply.github.com> Date: Mon, 10 Feb 2025 15:54:54 -0600 Subject: [PATCH 9/9] update puclic CI workflow for all integer dtypes (#2298) In this PR, the GitHub workflow is update to run the test suit with all integer dtypes when the lates python is used. In addition, newly added tests are updated to pass with all integer dtypes. --- .github/workflows/conda-package.yml | 261 ++------------------ dpnp/dpnp_utils/dpnp_utils_linearalgebra.py | 4 +- dpnp/tests/test_indexing.py | 20 +- dpnp/tests/test_linalg.py | 4 +- dpnp/tests/test_product.py | 14 +- dpnp/tests/test_statistics.py | 10 +- 6 files changed, 63 insertions(+), 250 deletions(-) diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index cf455180e18a..8994eb724730 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -16,6 +16,7 @@ env: CONDA_BUILD_INDEX_ENV_PY_VER: '3.12' # conda does not support python 3.13 CONDA_BUILD_VERSION: '25.1.1' CONDA_INDEX_VERSION: '0.5.0' + LATEST_PYTHON: '3.13' RERUN_TESTS_ON_FAILURE: 'true' RUN_TESTS_MAX_ATTEMPTS: 2 TEST_ENV_NAME: 'test' @@ -211,14 +212,19 @@ jobs: - name: Run tests if: env.RERUN_TESTS_ON_FAILURE != 'true' run: | - python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + if [[ ${{ matrix.python }} == ${{ env.LATEST_PYTHON }} ]]; then + export DPNP_TEST_ALL_INT_TYPES=1 + python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + else + python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + fi - name: Run tests if: env.RERUN_TESTS_ON_FAILURE == 'true' id: run_tests_linux uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0 with: - timeout_minutes: 15 + timeout_minutes: 25 max_attempts: ${{ env.RUN_TESTS_MAX_ATTEMPTS }} retry_on: any command: | @@ -226,112 +232,12 @@ jobs: . $CONDA/etc/profile.d/mamba.sh mamba activate ${{ env.TEST_ENV_NAME }} - python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests - - test_linux_all_dtypes: - name: Test_All_dtypes - - needs: build - - runs-on: ${{ matrix.os }} - - defaults: - run: - shell: bash -el {0} - - strategy: - fail-fast: false - matrix: - python: ['3.12'] - os: [ubuntu-latest] - - env: - channel-path: '${{ github.workspace }}/channel/' - pkg-path-in-channel: '${{ github.workspace }}/channel/linux-64/' - ver-json-path: '${{ github.workspace }}/version.json' - - steps: - - name: Download artifact - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }} - path: ${{ env.pkg-path-in-channel }} - - - name: Setup miniconda - id: setup_miniconda - continue-on-error: true - uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3.1.1 - with: - miniforge-version: latest - use-mamba: 'true' - channels: conda-forge - conda-remove-defaults: 'true' - python-version: ${{ env.CONDA_BUILD_INDEX_ENV_PY_VER}} - activate-environment: ${{ env.TEST_ENV_NAME }} - - - name: ReSetup miniconda - if: steps.setup_miniconda.outcome == 'failure' - uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3.1.1 - with: - miniforge-version: latest - use-mamba: 'true' - channels: conda-forge - conda-remove-defaults: 'true' - python-version: ${{ env.CONDA_BUILD_INDEX_ENV_PY_VER}} - activate-environment: ${{ env.TEST_ENV_NAME }} - - - name: Install conda-index - run: | - mamba install conda-index=${{ env.CONDA_INDEX_VERSION }} - - - name: Create conda channel - run: | - python -m conda_index ${{ env.channel-path }} - - - name: Test conda channel - run: | - 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 - run: | - export PACKAGE_VERSION=$(python -c "${{ env.VER_SCRIPT1 }} ${{ env.VER_SCRIPT2 }}") - - echo PACKAGE_VERSION=${PACKAGE_VERSION} - echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV - - # conda-index does not support python 3.13 - - name: Remove conda-index - run: mamba remove conda-index - - - name: Install dpnp - id: install_dpnp - continue-on-error: true - run: | - mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} - env: - TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.CHANNELS }}' - - - name: ReInstall dpnp - if: steps.install_dpnp.outcome == 'failure' - run: | - mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} - env: - TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.CHANNELS }}' - - - name: List installed packages - run: mamba list - - - name: Smoke test - run: | - python -c "import dpctl; dpctl.lsplatform()" - python -c "import dpnp; print(dpnp.__version__)" - - - name: Run tests for all dtypes - env: - DPNP_TEST_ALL_INT_TYPES: 1 - run: | - python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + if [[ ${{ matrix.python }} == ${{ env.LATEST_PYTHON }} ]]; then + export DPNP_TEST_ALL_INT_TYPES=1 + python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + else + python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + fi test_windows: name: Test @@ -453,141 +359,28 @@ jobs: - name: Run tests if: env.RERUN_TESTS_ON_FAILURE != 'true' run: | - python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + if (${{ matrix.python }} -eq ${{ env.LATEST_PYTHON }}) { + set DPNP_TEST_ALL_INT_TYPES=1 + python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + } else { + python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + } - name: Run tests if: env.RERUN_TESTS_ON_FAILURE == 'true' id: run_tests_win uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0 with: - timeout_minutes: 17 + timeout_minutes: 35 max_attempts: ${{ env.RUN_TESTS_MAX_ATTEMPTS }} retry_on: any command: | - python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests - - test_windows_all_dtypes: - name: Test_All_dtypes - - needs: build - - runs-on: ${{ matrix.os }} - - defaults: - run: - shell: cmd /C CALL {0} - - strategy: - fail-fast: false - matrix: - python: ['3.12'] - os: [windows-2019] - - env: - channel-path: '${{ github.workspace }}\channel\' - pkg-path-in-channel: '${{ github.workspace }}\channel\win-64\' - ver-json-path: '${{ github.workspace }}\version.json' - workdir: '${{ github.workspace }}' - - steps: - - name: Download artifact - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }} - path: ${{ env.pkg-path-in-channel }} - - - name: Store a path to package archive - run: | - @echo on - - set SEARCH_SCRIPT="DIR ${{ env.pkg-path-in-channel }} /s/b | FINDSTR /r "dpnp-.*\.conda"" - FOR /F "tokens=* USEBACKQ" %%F IN (`%SEARCH_SCRIPT%`) DO ( - SET FULL_PACKAGE_PATH=%%F - ) - echo FULL_PACKAGE_PATH: %FULL_PACKAGE_PATH% - (echo FULL_PACKAGE_PATH=%FULL_PACKAGE_PATH%) >> %GITHUB_ENV% - - - name: Setup miniconda - uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3.1.1 - with: - miniforge-version: latest - use-mamba: 'true' - channels: conda-forge - conda-remove-defaults: 'true' - python-version: ${{ env.CONDA_BUILD_INDEX_ENV_PY_VER}} - activate-environment: ${{ env.TEST_ENV_NAME }} - - - name: Store conda paths as envs - run: | - @echo on - (echo CONDA_LIB_PATH=%CONDA_PREFIX%\Library\lib\) >> %GITHUB_ENV% - (echo CONDA_LIB_BIN_PATH=%CONDA_PREFIX%\Library\bin\) >> %GITHUB_ENV% - - - name: Install conda-index - run: | - mamba install conda-index=${{ env.CONDA_INDEX_VERSION }} - - - name: Create conda channel - run: | - @echo on - python -m conda_index ${{ env.channel-path }} - - - name: Test conda channel - run: | - @echo on - 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 }} - - - name: Get package version - run: | - @echo on - set "SCRIPT=${{ env.VER_SCRIPT1 }} ${{ env.VER_SCRIPT2 }}" - FOR /F "tokens=* USEBACKQ" %%F IN (`python -c "%SCRIPT%"`) DO ( - set PACKAGE_VERSION=%%F - ) - echo PACKAGE_VERSION: %PACKAGE_VERSION% - (echo PACKAGE_VERSION=%PACKAGE_VERSION%) >> %GITHUB_ENV% - - # conda-index does not support python 3.13 - - name: Remove conda-index - run: mamba remove conda-index - - - name: Install dpnp - run: | - @echo on - mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} - env: - TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.CHANNELS }}' - MAMBA_NO_LOW_SPEED_LIMIT: 1 - - - name: List installed packages - run: mamba list - - - name: Activate OCL CPU RT - shell: pwsh - run: | - $script_path="$env:CONDA_PREFIX\Scripts\set-intel-ocl-icd-registry.ps1" - if (Test-Path $script_path) { - &$script_path - } else { - Write-Warning "File $script_path was NOT found!" - } - # Check the variable assisting OpenCL CPU driver to find TBB DLLs which are not located where it expects them by default - $cl_cfg="$env:CONDA_PREFIX\Library\lib\cl.cfg" - Get-Content -Tail 5 -Path $cl_cfg - - - name: Smoke test - run: | - python -c "import dpctl; dpctl.lsplatform()" - python -c "import dpnp; print(dpnp.__version__)" - - - name: Run tests for all dtypes - env: - DPNP_TEST_ALL_INT_TYPES: 1 - run: | - python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + if ( ${{ matrix.python }} -eq ${{ env.LATEST_PYTHON }} ) { + set DPNP_TEST_ALL_INT_TYPES=1 + python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + } else { + python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + } upload: name: Upload diff --git a/dpnp/dpnp_utils/dpnp_utils_linearalgebra.py b/dpnp/dpnp_utils/dpnp_utils_linearalgebra.py index 5767fdd4e52f..8dfc3b5e0ffe 100644 --- a/dpnp/dpnp_utils/dpnp_utils_linearalgebra.py +++ b/dpnp/dpnp_utils/dpnp_utils_linearalgebra.py @@ -509,8 +509,8 @@ def _gemm_special_case(x1, x2, res_dtype, call_flag): while `gemv` does not. """ - # TODO: replace with dpnp.int8 when it is added - is_int8 = x1.dtype == numpy.int8 and x2.dtype == numpy.int8 + + is_int8 = x1.dtype == dpnp.int8 and x2.dtype == dpnp.int8 is_int32_or_f32 = res_dtype in [dpnp.int32, dpnp.float32] flag = is_int8 and is_int32_or_f32 and call_flag in ["gemm", "gemm_batch"] diff --git a/dpnp/tests/test_indexing.py b/dpnp/tests/test_indexing.py index 78b0407bf340..1efef172cf6c 100644 --- a/dpnp/tests/test_indexing.py +++ b/dpnp/tests/test_indexing.py @@ -473,7 +473,7 @@ def test_input_1d(self, a_dt, indices, ind_dt, ivals, mode): b.put(ind, vals, mode=mode) ib.put(iind, ivals, mode=mode) assert_array_equal(ib, b) - elif numpy.issubdtype(ind_dt, numpy.uint64): + elif 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) @@ -508,7 +508,7 @@ def test_input_2d(self, a_dt, indices, ind_dt, mode): ind = get_abs_array(indices, ind_dt) iind = dpnp.array(ind) - if numpy.issubdtype(ind_dt, numpy.uint64): + if 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) @@ -656,7 +656,7 @@ 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) - if numpy.issubdtype(idx_dt, numpy.uint64): + if 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) @@ -701,7 +701,7 @@ 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): + elif 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 @@ -726,7 +726,7 @@ def test_2d(self, a_dt, ind_dt, indices, mode, axis): ind = get_abs_array(indices, ind_dt) ia, iind = dpnp.array(a), dpnp.array(ind) - if numpy.issubdtype(ind_dt, numpy.uint64): + if 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) @@ -1461,6 +1461,16 @@ def test_choose_inds_all_dtypes(self, dtype): chcs = dpnp.ones(1, dtype=dtype) with pytest.raises(TypeError): dpnp.choose(inds, chcs) + elif dtype == numpy.uint64: + # For this special case, NumPy raises an error but dpnp works + inds_np = numpy.array([1, 0, 1], dtype=dtype) + inds = dpnp.array(inds_np) + chcs_np = numpy.array([1, 2, 3], dtype=dtype) + chcs = dpnp.array(chcs_np) + assert_raises(TypeError, numpy.choose, inds_np, chcs_np) + expected = numpy.choose(inds_np.astype(numpy.int64), chcs_np) + result = dpnp.choose(inds, chcs) + assert_array_equal(expected, result) else: inds_np = numpy.array([1, 0, 1], dtype=dtype) inds = dpnp.array(inds_np) diff --git a/dpnp/tests/test_linalg.py b/dpnp/tests/test_linalg.py index 7f1ae77966fa..7e0fb98ea498 100644 --- a/dpnp/tests/test_linalg.py +++ b/dpnp/tests/test_linalg.py @@ -2401,10 +2401,10 @@ def test_qr(self, dtype, shape, mode): decimal=5, ) else: # mode=="raw" - assert_dtype_allclose(dpnp_q, np_q) + assert_dtype_allclose(dpnp_q, np_q, factor=24) if mode in ("raw", "r"): - assert_dtype_allclose(dpnp_r, np_r) + assert_dtype_allclose(dpnp_r, np_r, factor=24) @pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True)) @pytest.mark.parametrize( diff --git a/dpnp/tests/test_product.py b/dpnp/tests/test_product.py index 6629e55aafb2..b7cbfcf61e6d 100644 --- a/dpnp/tests/test_product.py +++ b/dpnp/tests/test_product.py @@ -836,7 +836,11 @@ def test_dtype_matrix(self, dt_in1, dt_in2, dt_out, shape1, shape2): assert_allclose(result, expected, rtol=1e-5, atol=1e-5) else: assert_raises(TypeError, dpnp.matmul, ia, ib, dtype=dt_out) - assert_raises(TypeError, numpy.matmul, a, b, dtype=dt_out) + # If one of the inputs is `uint64`, and dt_out is not unsigned int + # NumPy raises TypeError when `out` is provide but not when `dtype` + # is provided. dpnp raises TypeError in both cases as expected + if a.dtype != numpy.uint64 and b.dtype != numpy.uint64: + assert_raises(TypeError, numpy.matmul, a, b, dtype=dt_out) assert_raises(TypeError, dpnp.matmul, ia, ib, out=iout) assert_raises(TypeError, numpy.matmul, a, b, out=out) @@ -1444,8 +1448,8 @@ def setup_method(self): ], ) 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, ib = dpnp.array(a), dpnp.array(b) result = dpnp.matvec(ia, ib) @@ -2170,8 +2174,8 @@ def setup_method(self): ], ) 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, ib = dpnp.array(a), dpnp.array(b) result = dpnp.vecmat(ia, ib) diff --git a/dpnp/tests/test_statistics.py b/dpnp/tests/test_statistics.py index d5d0e72b030d..eb064334378f 100644 --- a/dpnp/tests/test_statistics.py +++ b/dpnp/tests/test_statistics.py @@ -219,8 +219,14 @@ def test_correlate(self, a, v, mode, dtype, method): @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("method", ["auto", "direct", "fft"]) def test_correlate_random(self, a_size, v_size, mode, dtype, method): - an = generate_random_numpy_array(a_size, dtype, probability=0.9) - vn = generate_random_numpy_array(v_size, dtype, probability=0.9) + if dtype in [numpy.int8, numpy.uint8]: + pytest.skip("avoid overflow.") + an = generate_random_numpy_array( + a_size, dtype, low=-3, high=3, probability=0.9 + ) + vn = generate_random_numpy_array( + v_size, dtype, low=-3, high=3, probability=0.9 + ) ad = dpnp.array(an) vd = dpnp.array(vn)