diff --git a/CHANGELOG.md b/CHANGELOG.md index dd3031c6547..6f24b204475 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ This release is compatible with NumPy 2.4.5. * Fixed `conda build` command syntax in GitHub workflows and documentation to use `conda-build` [#2888](https://github.com/IntelPython/dpnp/pull/2888) * Fixed incorrect `dpnp.tensor.acosh` result for `complex(±0, NaN)` special case to match the Python Array API specification [#2914](https://github.com/IntelPython/dpnp/pull/2914) * Fixed fork PR documentation workflow failures by implementing conditional publishing strategy: upstream PRs publish to GitHub Pages with comment, fork PRs upload artifacts [#2910](https://github.com/IntelPython/dpnp/pull/2910) +* Fixed incorrect `dpnp.tensor.expm1` result for `complex(±0, 0)` special case on CPU to match the Python Array API specification [#2926](https://github.com/IntelPython/dpnp/pull/2926) ### Security diff --git a/dpnp/tensor/libtensor/include/kernels/elementwise_functions/expm1.hpp b/dpnp/tensor/libtensor/include/kernels/elementwise_functions/expm1.hpp index e9e2a704cf0..735cb1fada5 100644 --- a/dpnp/tensor/libtensor/include/kernels/elementwise_functions/expm1.hpp +++ b/dpnp/tensor/libtensor/include/kernels/elementwise_functions/expm1.hpp @@ -121,6 +121,10 @@ struct Expm1Functor } } + if (x == realT(0) && y == realT(0)) { + return resT{realT(0), y}; + } + // x, y finite numbers const realT cosY_val = sycl::cos(y); const realT sinY_val = (y == 0) ? y : sycl::sin(y); diff --git a/dpnp/tests/tensor/elementwise/test_expm1.py b/dpnp/tests/tensor/elementwise/test_expm1.py index bb665c42456..e7c7765baa5 100644 --- a/dpnp/tests/tensor/elementwise/test_expm1.py +++ b/dpnp/tests/tensor/elementwise/test_expm1.py @@ -147,6 +147,7 @@ def test_expm1_special_cases(): num_finite = 1.0 vals = [ complex(0.0, 0.0), + complex(-0.0, 0.0), complex(num_finite, dpt.inf), complex(num_finite, dpt.nan), complex(dpt.inf, 0.0), @@ -165,6 +166,7 @@ def test_expm1_special_cases(): c_nan = complex(np.nan, np.nan) res = np.asarray( [ + complex(0.0, 0.0), complex(0.0, 0.0), c_nan, c_nan, @@ -184,4 +186,11 @@ def test_expm1_special_cases(): tol = dpt.finfo(X.dtype).resolution with np.errstate(invalid="ignore"): - assert_allclose(dpt.asnumpy(dpt.expm1(X)), res, atol=tol, rtol=tol) + Y = dpt.asnumpy(dpt.expm1(X)) + assert_allclose(Y, res, atol=tol, rtol=tol) + + # assert_allclose treats +0 == -0 + # verify sign bits for zero cases + for i in (0, 1): + assert not np.signbit(Y[i].real) + assert not np.signbit(Y[i].imag)