Skip to content

Commit d1ff2e7

Browse files
authored
update dpnp.ndarray.item (#2138)
* update dpnp.ndarray.item * address comments
1 parent 770042e commit d1ff2e7

File tree

3 files changed

+62
-24
lines changed

3 files changed

+62
-24
lines changed

dpnp/dpnp_array.py

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ def flatten(self, order="C"):
989989
990990
Returns
991991
-------
992-
out: dpnp.ndarray
992+
out : dpnp.ndarray
993993
A copy of the input array, flattened to one dimension.
994994
995995
See Also
@@ -1052,40 +1052,55 @@ def imag(self, value):
10521052
else:
10531053
raise TypeError("array does not have imaginary part to set")
10541054

1055-
def item(self, id=None):
1055+
def item(self, *args):
10561056
"""
10571057
Copy an element of an array to a standard Python scalar and return it.
10581058
10591059
For full documentation refer to :obj:`numpy.ndarray.item`.
10601060
1061+
Parameters
1062+
----------
1063+
*args : {none, int, tuple of ints}
1064+
- none: in this case, the method only works for arrays with
1065+
one element (``a.size == 1``), which element is copied into a
1066+
standard Python scalar object and returned.
1067+
- int: this argument is interpreted as a flat index into the array,
1068+
specifying which element to copy and return.
1069+
- tuple of ints: functions as does a single int argument, except
1070+
that the argument is interpreted as an nd-index into the array.
1071+
1072+
Returns
1073+
-------
1074+
out : Standard Python scalar object
1075+
A copy of the specified element of the array as a suitable Python scalar.
1076+
10611077
Examples
10621078
--------
1079+
>>> import dpnp as np
10631080
>>> np.random.seed(123)
10641081
>>> x = np.random.randint(9, size=(3, 3))
10651082
>>> x
1066-
array([[2, 2, 6],
1067-
[1, 3, 6],
1068-
[1, 0, 1]])
1083+
array([[0, 0, 7],
1084+
[6, 6, 6],
1085+
[0, 7, 1]])
10691086
>>> x.item(3)
1070-
1
1087+
6
10711088
>>> x.item(7)
1072-
0
1089+
7
10731090
>>> x.item((0, 1))
1074-
2
1091+
0
10751092
>>> x.item((2, 2))
10761093
1
10771094
1078-
"""
1095+
>>> x = np.array(5)
1096+
>>> x.item()
1097+
5
10791098
1080-
if id is None:
1081-
if self.size != 1:
1082-
raise ValueError(
1083-
"DPNP ndarray::item(): can only convert an array of size 1 to a Python scalar"
1084-
)
1085-
else:
1086-
id = 0
1099+
"""
10871100

1088-
return self.flat[id]
1101+
# TODO: implement a more efficient way to avoid copying to host
1102+
# for large arrays using `asnumpy()`
1103+
return self.asnumpy().item(*args)
10891104

10901105
@property
10911106
def itemsize(self):

tests/test_ndarray.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def test_flatten(arr, arr_dtype):
5555
[(), 0, (0,), (2), (5, 2), (5, 0, 2), (5, 3, 2)],
5656
ids=["()", "0", "(0,)", "(2)", "(5, 2)", "(5, 0, 2)", "(5, 3, 2)"],
5757
)
58-
@pytest.mark.parametrize("order", ["C", "F"], ids=["C", "F"])
58+
@pytest.mark.parametrize("order", ["C", "F"])
5959
def test_flags(shape, order):
6060
usm_array = dpt.usm_ndarray(shape, order=order)
6161
numpy_array = numpy.ndarray(shape, order=order)
@@ -71,7 +71,7 @@ def test_flags(shape, order):
7171
ids=["complex64", "float32", "int64", "int32", "bool"],
7272
)
7373
@pytest.mark.parametrize("strides", [(1, 4), (4, 1)], ids=["(1, 4)", "(4, 1)"])
74-
@pytest.mark.parametrize("order", ["C", "F"], ids=["C", "F"])
74+
@pytest.mark.parametrize("order", ["C", "F"])
7575
def test_flags_strides(dtype, order, strides):
7676
itemsize = numpy.dtype(dtype).itemsize
7777
numpy_strides = tuple([el * itemsize for el in strides])
@@ -104,6 +104,32 @@ def test_flags_writable():
104104
assert not a.imag.flags.writable
105105

106106

107+
class TestItem:
108+
@pytest.mark.parametrize("args", [2, 7, (1, 2), (2, 0)])
109+
def test_basic(self, args):
110+
a = numpy.arange(12).reshape(3, 4)
111+
ia = dpnp.array(a)
112+
113+
expected = a.item(args)
114+
result = ia.item(args)
115+
assert isinstance(result, int)
116+
assert expected == result
117+
118+
def test_0D(self):
119+
a = numpy.array(5)
120+
ia = dpnp.array(a)
121+
122+
expected = a.item()
123+
result = ia.item()
124+
assert isinstance(result, int)
125+
assert expected == result
126+
127+
def test_error(self):
128+
ia = dpnp.arange(12).reshape(3, 4)
129+
with pytest.raises(ValueError):
130+
ia.item()
131+
132+
107133
def test_print_dpnp_int():
108134
result = repr(dpnp.array([1, 0, 2, -3, -1, 2, 21, -9], dtype="i4"))
109135
expected = "array([ 1, 0, 2, -3, -1, 2, 21, -9], dtype=int32)"
@@ -165,9 +191,7 @@ def test_print_dpnp_boolean():
165191
assert result == expected
166192

167193

168-
@pytest.mark.parametrize(
169-
"character", [dpnp.nan, dpnp.inf], ids=["dpnp.nan", "dpnp.inf"]
170-
)
194+
@pytest.mark.parametrize("character", [dpnp.nan, dpnp.inf])
171195
def test_print_dpnp_special_character(character):
172196
result = repr(dpnp.array([1.0, 0.0, character, 3.0]))
173197
expected = f"array([ 1., 0., {character}, 3.])"
@@ -264,7 +288,7 @@ def test_array_as_index(shape, index_dtype):
264288
@pytest.mark.parametrize(
265289
"shape",
266290
[(3, 5), (2, 5, 2), (2, 3, 3, 6)],
267-
ids=["(3,5)", "(2,5,2)", "(2,3,3,6)"],
291+
ids=["(3, 5)", "(2, 5, 2)", "(2, 3, 3, 6)"],
268292
)
269293
def test_matrix_transpose(shape):
270294
a = numpy.arange(numpy.prod(shape)).reshape(shape)

tests/third_party/cupy/core_tests/test_ndarray_conversion.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
{"shape": (1,)},
1313
{"shape": (1, 1, 1)},
1414
)
15-
@pytest.mark.usefixtures("allow_fall_back_on_numpy")
1615
class TestNdarrayItem(unittest.TestCase):
1716
@testing.for_all_dtypes()
1817
@testing.numpy_cupy_equal()

0 commit comments

Comments
 (0)