Skip to content

Commit bd0cad2

Browse files
author
Vahid Tavanashad
committed
align dpnp.fix with numpy 2.2
1 parent 48d36a4 commit bd0cad2

File tree

4 files changed

+81
-107
lines changed

4 files changed

+81
-107
lines changed

dpnp/backend/extensions/ufunc/elementwise_functions/fix.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,15 @@ template <typename T>
6060
struct OutputType
6161
{
6262
using value_type =
63-
typename std::disjunction<td_ns::TypeMapResultEntry<T, sycl::half>,
63+
typename std::disjunction<td_ns::TypeMapResultEntry<T, std::uint8_t>,
64+
td_ns::TypeMapResultEntry<T, std::uint16_t>,
65+
td_ns::TypeMapResultEntry<T, std::uint32_t>,
66+
td_ns::TypeMapResultEntry<T, std::uint64_t>,
67+
td_ns::TypeMapResultEntry<T, std::int8_t>,
68+
td_ns::TypeMapResultEntry<T, std::int16_t>,
69+
td_ns::TypeMapResultEntry<T, std::int32_t>,
70+
td_ns::TypeMapResultEntry<T, std::int64_t>,
71+
td_ns::TypeMapResultEntry<T, sycl::half>,
6472
td_ns::TypeMapResultEntry<T, float>,
6573
td_ns::TypeMapResultEntry<T, double>,
6674
td_ns::DefaultResultEntry<void>>::result_type;

dpnp/backend/kernels/elementwise_functions/fix.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,12 @@ struct FixFunctor
4343

4444
resT operator()(const argT &x) const
4545
{
46-
return (x >= 0.0) ? sycl::floor(x) : sycl::ceil(x);
46+
if constexpr (std::is_integral_v<argT>) {
47+
return x;
48+
}
49+
else {
50+
return (x >= 0.0) ? sycl::floor(x) : sycl::ceil(x);
51+
}
4752
}
4853
};
4954
} // namespace dpnp::kernels::fix

dpnp/dpnp_iface_mathematical.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1728,14 +1728,14 @@ def ediff1d(ary, to_end=None, to_begin=None):
17281728
Round to nearest integer towards zero.
17291729
17301730
Round an array of floats element-wise to nearest integer towards zero.
1731-
The rounded values are returned as floats.
1731+
The rounded values have the same data-type as the input.
17321732
17331733
For full documentation refer to :obj:`numpy.fix`.
17341734
17351735
Parameters
17361736
----------
17371737
x : {dpnp.ndarray, usm_ndarray}
1738-
An array of floats to be rounded.
1738+
Input array, expected to have a real-valued data type.
17391739
out : {None, dpnp.ndarray, usm_ndarray}, optional
17401740
Output array to populate.
17411741
Array must have the correct shape and the expected data type.
@@ -1749,12 +1749,11 @@ def ediff1d(ary, to_end=None, to_begin=None):
17491749
Returns
17501750
-------
17511751
out : dpnp.ndarray
1752-
An array with the rounded values and with the same dimensions as the input.
1753-
The returned array will have a floating point data type that input can cast
1754-
to it safely considering device capabilities.
1755-
If `out` is ``None`` then a float array is returned with the rounded values.
1756-
Otherwise the result is stored there and the return value `out` is
1757-
a reference to that array.
1752+
An array with the same dimensions and data-type as the input.
1753+
If second argument is not supplied then a new array is returned
1754+
with the rounded values.
1755+
If a second argument is supplied the result is stored there.
1756+
The return value `out` is then a reference to that array.
17581757
17591758
Limitations
17601759
-----------

dpnp/tests/test_mathematical.py

Lines changed: 59 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -750,75 +750,6 @@ def test_errors(self):
750750
assert_raises(ExecutionPlacementError, dpnp.ediff1d, ia, to_end=to_end)
751751

752752

753-
class TestFix:
754-
def get_numpy_output_dtype(self, dtype):
755-
# this is used to determine the output dtype of numpy array
756-
# which is on cpu so no need for checking has_support_aspect64
757-
if has_support_aspect16() and dpnp.can_cast(dtype, dpnp.float16):
758-
return dpnp.float16
759-
if dpnp.can_cast(dtype, dpnp.float32):
760-
return dpnp.float32
761-
if dpnp.can_cast(dtype, dpnp.float64):
762-
return dpnp.float64
763-
764-
@pytest.mark.parametrize(
765-
"dt", get_all_dtypes(no_none=True, no_complex=True)
766-
)
767-
def test_basic(self, dt):
768-
a = get_abs_array([[1.0, 1.1, 1.5, 1.8], [-1.0, -1.1, -1.5, -1.8]], dt)
769-
ia = dpnp.array(a)
770-
771-
result = dpnp.fix(ia)
772-
expected = numpy.fix(a)
773-
assert_array_equal(result, expected)
774-
775-
@pytest.mark.parametrize("xp", [numpy, dpnp])
776-
@pytest.mark.parametrize("dt", get_complex_dtypes())
777-
def test_complex(self, xp, dt):
778-
a = xp.array([1.1, -1.1], dtype=dt)
779-
with pytest.raises((ValueError, TypeError)):
780-
xp.fix(a)
781-
782-
@pytest.mark.parametrize(
783-
"dt", get_all_dtypes(no_none=True, no_complex=True)
784-
)
785-
def test_out(self, dt):
786-
data = [[1.0, 1.1, 1.5, 1.8], [-1.0, -1.1, -1.5, -1.8]]
787-
a = get_abs_array(data, dtype=dt)
788-
# numpy output has the same dtype as input
789-
# dpnp output always has a floating point dtype
790-
dt_out = self.get_numpy_output_dtype(a.dtype)
791-
out = numpy.zeros_like(a, dtype=dt_out)
792-
ia, iout = dpnp.array(a), dpnp.array(out)
793-
794-
result = dpnp.fix(ia, out=iout)
795-
expected = numpy.fix(a, out=out)
796-
assert_array_equal(result, expected)
797-
798-
@pytest.mark.skipif(not has_support_aspect16(), reason="no fp16 support")
799-
def test_out_float16(self):
800-
data = [[1.0, 1.1], [1.5, 1.8], [-1.0, -1.1], [-1.5, -1.8]]
801-
a = numpy.array(data, dtype=numpy.float16)
802-
out = numpy.zeros_like(a, dtype=numpy.float16)
803-
ia, iout = dpnp.array(a), dpnp.array(out)
804-
805-
result = dpnp.fix(ia, out=iout)
806-
expected = numpy.fix(a, out=out)
807-
assert_array_equal(result, expected)
808-
809-
@pytest.mark.parametrize("xp", [numpy, dpnp])
810-
@pytest.mark.parametrize("dt", [bool] + get_integer_dtypes())
811-
def test_out_invalid_dtype(self, xp, dt):
812-
a = xp.array([[1.5, 1.8], [-1.0, -1.1]])
813-
out = xp.zeros_like(a, dtype=dt)
814-
815-
with pytest.raises((ValueError, TypeError)):
816-
xp.fix(a, out=out)
817-
818-
def test_scalar(self):
819-
assert_raises(TypeError, dpnp.fix, -3.4)
820-
821-
822753
class TestGradient:
823754
@pytest.mark.parametrize("dt", get_all_dtypes(no_none=True, no_bool=True))
824755
def test_basic(self, dt):
@@ -2274,50 +2205,81 @@ def test_projection(self, dtype):
22742205
assert dpnp.allclose(result, expected)
22752206

22762207

2277-
@pytest.mark.parametrize("func", ["ceil", "floor", "trunc"])
2208+
@pytest.mark.parametrize("func", ["ceil", "floor", "trunc", "fix"])
22782209
class TestRoundingFuncs:
22792210
@pytest.mark.parametrize(
2280-
"dtype", get_all_dtypes(no_none=True, no_complex=True)
2211+
"dt", get_all_dtypes(no_none=True, no_complex=True)
22812212
)
2282-
def test_out(self, func, dtype):
2283-
a = generate_random_numpy_array(10, dtype)
2213+
def test_basic(self, func, dt):
2214+
a = generate_random_numpy_array((2, 4), dt)
2215+
ia = dpnp.array(a)
2216+
2217+
result = getattr(dpnp, func)(ia)
22842218
expected = getattr(numpy, func)(a)
2219+
assert_array_equal(result, expected)
22852220

2286-
ia = dpnp.array(a)
2287-
out_dt = numpy.int8 if dtype == dpnp.bool else dtype
2288-
iout = dpnp.empty(expected.shape, dtype=out_dt)
2221+
@pytest.mark.parametrize("xp", [numpy, dpnp])
2222+
@pytest.mark.parametrize("dt", get_complex_dtypes())
2223+
def test_complex(self, func, xp, dt):
2224+
a = xp.array([1.1, -1.1], dtype=dt)
2225+
with pytest.raises((ValueError, TypeError)):
2226+
getattr(xp, func)(a)
2227+
2228+
@testing.with_requires("numpy>=2.1.0")
2229+
@pytest.mark.parametrize(
2230+
"dt", get_all_dtypes(no_none=True, no_complex=True)
2231+
)
2232+
def test_out(self, func, dt):
2233+
a = generate_random_numpy_array(10, dt)
2234+
dt_out = numpy.int8 if dt == dpnp.bool else dt
2235+
out = numpy.empty(a.shape, dtype=dt_out)
2236+
ia, iout = dpnp.array(a), dpnp.array(out)
2237+
2238+
expected = getattr(numpy, func)(a, out=out)
22892239
result = getattr(dpnp, func)(ia, out=iout)
2240+
assert result is iout
2241+
assert_array_equal(result, expected)
22902242

2243+
@pytest.mark.skipif(not has_support_aspect16(), reason="no fp16 support")
2244+
def test_out_float16(self, func):
2245+
a = generate_random_numpy_array((4, 2), numpy.float16)
2246+
out = numpy.zeros_like(a, dtype=numpy.float16)
2247+
ia, iout = dpnp.array(a), dpnp.array(out)
2248+
2249+
result = getattr(dpnp, func)(ia, out=iout)
2250+
expected = getattr(numpy, func)(a, out=out)
22912251
assert result is iout
2292-
# numpy.ceil, numpy.floor, numpy.trunc always return float dtype for
2293-
# NumPy < 2.1.0 while output has the dtype of input for NumPy >= 2.1.0
2294-
# (dpnp follows the latter behavior except for boolean dtype where it
2295-
# returns int8)
2296-
if numpy_version() < "2.1.0" or dtype == dpnp.bool:
2297-
check_type = False
2298-
else:
2299-
check_type = True
2300-
assert_dtype_allclose(result, expected, check_type=check_type)
2252+
assert_array_equal(result, expected)
23012253

2254+
@pytest.mark.parametrize("xp", [numpy, dpnp])
23022255
@pytest.mark.parametrize(
2303-
"dtype", get_all_dtypes(no_complex=True, no_none=True)[:-1]
2256+
"dt_out", get_all_dtypes(no_none=True, no_complex=True)[:-1]
23042257
)
2305-
def test_invalid_dtype(self, func, dtype):
2306-
dpnp_dtype = get_all_dtypes(no_complex=True, no_none=True)[-1]
2307-
ia = dpnp.arange(10, dtype=dpnp_dtype)
2308-
iout = dpnp.empty(10, dtype=dtype)
2309-
2310-
with pytest.raises(ValueError):
2311-
getattr(dpnp, func)(ia, out=iout)
2258+
def test_invalid_dtype(self, func, xp, dt_out):
2259+
dt_in = get_all_dtypes(no_none=True, no_complex=True)[-1]
2260+
a = xp.arange(10, dtype=dt_in)
2261+
out = xp.empty(10, dtype=dt_out)
2262+
if dt_out == numpy.float32 and dt_in == numpy.float64:
2263+
if xp == dpnp:
2264+
# NumPy allows "same_kind" casting, dpnp does not
2265+
assert_raises(ValueError, getattr(dpnp, func), a, out=out)
2266+
else:
2267+
numpy_error = numpy._core._exceptions._UFuncOutputCastingError
2268+
assert_raises(
2269+
(ValueError, numpy_error), getattr(xp, func), a, out=out
2270+
)
23122271

2272+
@pytest.mark.parametrize("xp", [numpy, dpnp])
23132273
@pytest.mark.parametrize(
23142274
"shape", [(0,), (15,), (2, 2)], ids=["(0,)", "(15,)", "(2, 2)"]
23152275
)
2316-
def test_invalid_shape(self, func, shape):
2317-
ia = dpnp.arange(10, dtype=dpnp.float32)
2318-
iout = dpnp.empty(shape, dtype=dpnp.float32)
2276+
def test_invalid_shape(self, func, xp, shape):
2277+
a = xp.arange(10, dtype=xp.float32)
2278+
out = xp.empty(shape, dtype=xp.float32)
2279+
assert_raises(ValueError, getattr(xp, func), a, out=out)
23192280

2320-
assert_raises(ValueError, getattr(dpnp, func), ia, out=iout)
2281+
def test_scalar(self, func):
2282+
assert_raises(TypeError, getattr(dpnp, func), -3.4)
23212283

23222284

23232285
class TestHypot:

0 commit comments

Comments
 (0)