Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.21.0] - MM/DD/2026
## [0.21.0] - 2026-MM-DD

This release is compatible with NumPy 2.4.5.

### Added

* Added C API functions for `dpnp.tensor.usm_ndarray` setters and getters to avoid ABI breakage if `dpnp.tensor.usm_ndarray` is modified [gh-2866](https://github.com/IntelPython/dpnp/pull/2866)

### Changed
* Changed `dpnp.meshgrid` and `dpnp.tensor.meshgrid` to return a tuple instead of a list, aligning with NumPy 2.5+ behavior and 2025.12 version of the Python array API standard [#2854](https://github.com/IntelPython/dpnp/pull/2854)

* Changed `dpnp.meshgrid` and `dpnp.tensor.meshgrid` to return a tuple instead of a list, aligning with NumPy 2.5+ behavior and 2025.12 version of the Python array API standard [#2854](https://github.com/IntelPython/dpnp/pull/2854)
* Updated `searchsorted` implementations to align with the 2025.12 array API spec [gh-2902](https://github.com/IntelPython/dpnp/pull/2902)
* Updated tests to align with NumPy 2.4.5 compatibility [gh-2920](https://github.com/IntelPython/dpnp/pull/2920)

### Deprecated

Expand Down
19 changes: 12 additions & 7 deletions dpnp/tests/test_binary_ufuncs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1014,16 +1014,21 @@ def test_broadcasting(self, func, dt):
result = getattr(dpnp, func)(ia, b)
assert_array_equal(result, expected)

@pytest.mark.parametrize("dt", [numpy.int32, numpy.int64])
def test_gcd_overflow(self, dt):
a = dt(numpy.iinfo(dt).min) # negative power of two
ia = dpnp.array(a)
q = -(a // 4)
@pytest.mark.parametrize("sign", [1, -1])
@pytest.mark.parametrize("dt", get_integer_dtypes(no_unsigned=True))
def test_gcd_overflow(self, sign, dt):
a = dt(numpy.iinfo(dt).min) # INT_MIN
q = (a // 4) * sign
ia, iq = dpnp.array(a), dpnp.array(q)

# verify that we don't overflow when taking abs(x)
# not relevant for lcm, where the result is unrepresentable anyway
expected = numpy.gcd(a, q)
result = dpnp.gcd(ia, q)
expected = numpy.gcd(a, q * 3)
result = dpnp.gcd(ia, iq * 3)
assert_array_equal(result, expected)

expected = numpy.gcd(q * 3, a)
result = dpnp.gcd(iq * 3, ia)
assert_array_equal(result, expected)

def test_lcm_overflow(self):
Expand Down
7 changes: 4 additions & 3 deletions dpnp/tests/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,10 +661,11 @@ def test_empty(self, dtype, mode):
dpnp.put(ia, [1, 2, 3], [], mode=mode)
assert_array_equal(ia, a)

# TODO: enable test for numpy also since 2.0
@testing.with_requires("numpy>=2.0")
@pytest.mark.parametrize("xp", [dpnp, numpy])
@pytest.mark.parametrize("mode", ["clip", "wrap"])
def test_empty_input(self, mode):
empty = dpnp.asarray(list())
def test_empty_input(self, xp, mode):
empty = xp.asarray(list())
with pytest.raises(IndexError):
empty.put(1, 1, mode=mode)

Expand Down
18 changes: 3 additions & 15 deletions dpnp/tests/test_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,7 @@ def test_empty(self, shape, p):
expected = numpy.linalg.cond(a, p=p)
assert_dtype_allclose(result, expected)

# TODO: uncomment once numpy 2.3.3 release is published
# @testing.with_requires("numpy>=2.3.3")
@testing.with_requires("numpy>=2.3.3")
@pytest.mark.parametrize(
"dtype", get_all_dtypes(no_none=True, no_bool=True)
)
Expand All @@ -305,9 +304,6 @@ def test_basic(self, dtype, shape, p):

result = dpnp.linalg.cond(ia, p=p)
expected = numpy.linalg.cond(a, p=p)
# TODO: remove when numpy#29333 is released
if numpy_version() < "2.3.3":
expected = expected.real
assert_dtype_allclose(result, expected, factor=16)

@pytest.mark.parametrize("p", _norms)
Expand Down Expand Up @@ -3238,8 +3234,7 @@ def test_errors(self):
ValueError, dpnp.linalg.matrix_rank, a_dp, tol=1e-06, rtol=1e-04
)

# TODO: use below fixture when NumPy 2.5 is released
# @testing.with_requires("numpy>=2.5")
@testing.with_requires("numpy>=2.4.5")
@pytest.mark.parametrize(
"shape",
[
Expand All @@ -3258,14 +3253,7 @@ def test_empty(self, shape):
ia = dpnp.array(a)

result = dpnp.linalg.matrix_rank(ia)
if numpy_version() < "2.5.0": # TODO: remove
# Expected behavior: rank of empty matrix is 0
# For stacked matrices, return array of zeros
expected = numpy.zeros(shape[:-2], dtype=numpy.intp)
if expected.ndim == 0:
expected = numpy.array(0)
else:
expected = numpy.linalg.matrix_rank(a)
expected = numpy.linalg.matrix_rank(a)
assert_array_equal(result, expected, strict=True)

# Also test with hermitian=True
Expand Down
26 changes: 9 additions & 17 deletions dpnp/tests/test_manipulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
get_integer_float_dtypes,
get_unsigned_dtypes,
has_support_aspect64,
numpy_version,
)
from .third_party.cupy import testing

Expand Down Expand Up @@ -90,16 +89,15 @@ def test_size(self):

assert dpnp.size(ia, 1) == numpy.size(a, 1)

# TODO: include commented code in the test when numpy-2.4 is released
# @testing.with_requires("numpy>=2.4")
def test_size_tuple(self):
@testing.with_requires("numpy>=2.4.0")
@pytest.mark.parametrize("axis", [(), (0,), (1,), (0, 1)])
def test_size_tuple(self, axis):
a = [[1, 2, 3], [4, 5, 6]]
ia = dpnp.array(a)

assert dpnp.size(ia, ()) == 1 # numpy.size(a, ())
assert dpnp.size(ia, (0,)) == 2 # numpy.size(a, (0,))
assert dpnp.size(ia, (1,)) == 3 # numpy.size(a, (1,))
assert dpnp.size(ia, (0, 1)) == 6 # numpy.size(a, (0, 1))
result = dpnp.size(ia, axis=axis)
expected = numpy.size(a, axis=axis)
assert result == expected


class TestAppend:
Expand Down Expand Up @@ -1891,25 +1889,19 @@ def test_equal_nan(self, eq_nan_kwd):
expected = numpy.unique(a, **eq_nan_kwd)
assert_array_equal(result, expected)

# TODO: uncomment once numpy 2.4.0 release is published
# @testing.with_requires("numpy>=2.4.0")
@testing.with_requires("numpy>=2.4.0")
@pytest.mark.parametrize("axis", [0, -1])
def test_1d_equal_nan_axis(self, axis):
a = numpy.array([numpy.nan, 0, 0, numpy.nan])
ia = dpnp.array(a)

result = dpnp.unique(ia, axis=axis, equal_nan=True)
expected = numpy.unique(a, axis=axis, equal_nan=True)
# TODO: remove when numpy#29372 is released
if numpy_version() < "2.4.0":
expected = numpy.array([0.0, numpy.nan])
assert_array_equal(result, expected)

# TODO: uncomment once numpy 2.4.0 release is published
# @testing.with_requires("numpy>=2.4.0")
@testing.with_requires("numpy>=2.4.0")
@pytest.mark.parametrize("equal_nan", [True, False])
# @pytest.mark.parametrize("xp", [numpy, dpnp])
@pytest.mark.parametrize("xp", [dpnp])
@pytest.mark.parametrize("xp", [numpy, dpnp])
def test_1d_axis_float_raises_typeerror(self, xp, equal_nan):
a = xp.array([xp.nan, 0, 0, xp.nan])
with pytest.raises(TypeError, match="integer argument expected"):
Expand Down
7 changes: 3 additions & 4 deletions dpnp/tests/test_mathematical.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def test_angle_complex(self, dtype, deg):


class TestConj:
@testing.with_requires("numpy!=2.4.5")
@pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True))
def test_conj(self, dtype):
a = generate_random_numpy_array(20, dtype)
Expand Down Expand Up @@ -1674,15 +1675,13 @@ def test_zero(self, dt):
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")
@testing.with_requires("numpy>=2.3.0")
def test_zero_fp16(self):
a = numpy.array([0.0], dtype=numpy.float16)
ia = dpnp.array(a)

result = dpnp.sinc(ia)
# expected = numpy.sinc(a) # numpy returns NaN, but expected 1.0
expected = numpy.ones_like(a)
expected = numpy.sinc(a)
assert_dtype_allclose(result, expected)

@pytest.mark.usefixtures("suppress_invalid_numpy_warnings")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,35 @@ class TestConj:
@testing.numpy_cupy_array_almost_equal()
def test_conj(self, xp, dtype):
x = testing.shaped_arange((2, 3), xp, dtype)
if xp is numpy and numpy.__version__ == "2.4.5" and x.dtype == bool:
return x # NumPy 2.4.5 had a regression for bool_arr.conj()
return x.conj()

@testing.for_all_dtypes(no_complex=True)
@testing.numpy_cupy_array_almost_equal()
def test_conj_pass(self, xp, dtype):
x = testing.shaped_arange((2, 3), xp, dtype)
y = x.conj()
if xp is numpy and numpy.__version__ == "2.4.5":
return x # NumPy 2.4.5 had a regression for bool_arr.conj()
assert x is y
return y

@testing.for_all_dtypes()
@testing.numpy_cupy_array_almost_equal()
def test_conjugate(self, xp, dtype):
x = testing.shaped_arange((2, 3), xp, dtype)
if xp is numpy and numpy.__version__ == "2.4.5" and x.dtype == bool:
return x # NumPy 2.4.5 had a regression for bool_arr.conj()
return x.conjugate()

@testing.for_all_dtypes(no_complex=True)
@testing.numpy_cupy_array_almost_equal()
def test_conjugate_pass(self, xp, dtype):
x = testing.shaped_arange((2, 3), xp, dtype)
y = x.conjugate()
if xp is numpy and numpy.__version__ == "2.4.5":
return x # NumPy 2.4.5 had a regression for bool_arr.conj()
assert x is y
return y

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import numpy
import pytest

import dpnp as cp
from dpnp.tests.helper import has_support_aspect64
from dpnp.tests.third_party.cupy import testing

# TODO: remove once all dtype aliases added
cp.int8 = numpy.int8
cp.uint8 = numpy.uint8
cp.int16 = numpy.int16

# "example string" or
# ("example string", "xfail message")
examples = [
Expand Down
4 changes: 0 additions & 4 deletions dpnp/tests/third_party/cupy/indexing_tests/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,6 @@ 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)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import unittest

import numpy
Expand Down Expand Up @@ -226,7 +228,6 @@ def test_correlate_diff_types(self, xp, dtype1, dtype2, mode):


@testing.parameterize(*testing.product({"mode": ["valid", "same", "full"]}))
@pytest.mark.usefixtures("allow_fall_back_on_numpy")
class TestCorrelateInvalid(unittest.TestCase):

@testing.with_requires("numpy>=1.18")
Expand Down
Loading