Skip to content

Commit c4b3b2e

Browse files
npolina4antonwolfy
andauthored
Update dpnp.indices function (#1622)
* Update dpnp.indices function * Clean up dpnp_indices * address comments * address comments * cancel changes for test_indices_list3 * Added description of all parameters * Implement dpnp.mgrid and dpnp.ogrid function (#1633) * Implement dpnp.mgrid and dpnp.ogrid function * address comments * address comments * Skip dtype check for Iris Xe * Update test_ranges.py * Added description of all parameters * Resolve pre-commit issue --------- Co-authored-by: Anton <100830759+antonwolfy@users.noreply.github.com> Co-authored-by: Anton Volkov <antonwolfy@gmail.com>
1 parent 75c6539 commit c4b3b2e

File tree

11 files changed

+370
-77
lines changed

11 files changed

+370
-77
lines changed

dpnp/dpnp_algo/dpnp_algo_indexing.pxi

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ __all__ += [
4040
"dpnp_diag_indices",
4141
"dpnp_diagonal",
4242
"dpnp_fill_diagonal",
43-
"dpnp_indices",
4443
"dpnp_putmask",
4544
"dpnp_select",
4645
"dpnp_tril_indices",
@@ -237,40 +236,6 @@ cpdef dpnp_fill_diagonal(dpnp_descriptor x1, val):
237236
c_dpctl.DPCTLEvent_Delete(event_ref)
238237

239238

240-
cpdef object dpnp_indices(dimensions):
241-
len_dimensions = len(dimensions)
242-
res_shape = []
243-
res_shape.append(len_dimensions)
244-
for i in range(len_dimensions):
245-
res_shape.append(dimensions[i])
246-
247-
result = []
248-
if len_dimensions == 1:
249-
res = []
250-
for i in range(dimensions[0]):
251-
res.append(i)
252-
result.append(res)
253-
else:
254-
res1 = []
255-
for i in range(dimensions[0]):
256-
res = []
257-
for j in range(dimensions[1]):
258-
res.append(i)
259-
res1.append(res)
260-
result.append(res1)
261-
262-
res2 = []
263-
for i in range(dimensions[0]):
264-
res = []
265-
for j in range(dimensions[1]):
266-
res.append(j)
267-
res2.append(res)
268-
result.append(res2)
269-
270-
dpnp_result = dpnp.array(result)
271-
return dpnp_result
272-
273-
274239
cpdef dpnp_putmask(utils.dpnp_descriptor arr, utils.dpnp_descriptor mask, utils.dpnp_descriptor values):
275240
cdef int values_size = values.size
276241

dpnp/dpnp_algo/dpnp_arraycreation.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import math
12
import operator
23

4+
import dpctl.utils as dpu
35
import numpy
46

57
import dpnp
@@ -10,6 +12,7 @@
1012
"dpnp_geomspace",
1113
"dpnp_linspace",
1214
"dpnp_logspace",
15+
"dpnp_nd_grid",
1316
]
1417

1518

@@ -256,3 +259,134 @@ def dpnp_logspace(
256259
if dtype is None:
257260
return dpnp.power(base, res)
258261
return dpnp.power(base, res).astype(dtype, copy=False)
262+
263+
264+
class dpnp_nd_grid:
265+
"""
266+
Construct a multi-dimensional "meshgrid".
267+
268+
``grid = dpnp_nd_grid()`` creates an instance which will return a mesh-grid
269+
when indexed. The dimension and number of the output arrays are equal
270+
to the number of indexing dimensions. If the step length is not a
271+
complex number, then the stop is not inclusive.
272+
273+
However, if the step length is a complex number (e.g. 5j), then the
274+
integer part of its magnitude is interpreted as specifying the
275+
number of points to create between the start and stop values, where
276+
the stop value is inclusive.
277+
278+
If instantiated with an argument of ``sparse=True``, the mesh-grid is
279+
open (or not fleshed out) so that only one-dimension of each returned
280+
argument is greater than 1.
281+
282+
Parameters
283+
----------
284+
sparse : bool, optional
285+
Whether the grid is sparse or not. Default is False.
286+
287+
"""
288+
289+
def __init__(
290+
self, sparse=False, device=None, usm_type="device", sycl_queue=None
291+
):
292+
dpu.validate_usm_type(usm_type, allow_none=False)
293+
self.sparse = sparse
294+
self.usm_type = usm_type
295+
self.sycl_queue_normalized = dpnp.get_normalized_queue_device(
296+
sycl_queue=sycl_queue, device=device
297+
)
298+
299+
def __getitem__(self, key):
300+
if isinstance(key, slice):
301+
step = key.step
302+
stop = key.stop
303+
start = key.start
304+
if start is None:
305+
start = 0
306+
if isinstance(step, complex):
307+
step = abs(step)
308+
length = int(step)
309+
if step != 1:
310+
step = (stop - start) / float(step - 1)
311+
stop = stop + step
312+
return (
313+
dpnp.arange(
314+
0,
315+
length,
316+
1,
317+
dtype=dpnp.default_float_type(),
318+
usm_type=self.usm_type,
319+
sycl_queue=self.sycl_queue_normalized,
320+
)
321+
* step
322+
+ start
323+
)
324+
else:
325+
return dpnp.arange(
326+
start,
327+
stop,
328+
step,
329+
usm_type=self.usm_type,
330+
sycl_queue=self.sycl_queue_normalized,
331+
)
332+
333+
size = []
334+
dtype = int
335+
for k in range(len(key)):
336+
step = key[k].step
337+
start = key[k].start
338+
stop = key[k].stop
339+
if start is None:
340+
start = 0
341+
if step is None:
342+
step = 1
343+
if isinstance(step, complex):
344+
size.append(int(abs(step)))
345+
dtype = dpnp.default_float_type()
346+
else:
347+
size.append(
348+
int(math.ceil((key[k].stop - start) / (step * 1.0)))
349+
)
350+
if (
351+
isinstance(step, float)
352+
or isinstance(start, float)
353+
or isinstance(stop, float)
354+
):
355+
dtype = dpnp.default_float_type()
356+
if self.sparse:
357+
nn = [
358+
dpnp.arange(
359+
_x,
360+
dtype=_t,
361+
usm_type=self.usm_type,
362+
sycl_queue=self.sycl_queue_normalized,
363+
)
364+
for _x, _t in zip(size, (dtype,) * len(size))
365+
]
366+
else:
367+
nn = dpnp.indices(
368+
size,
369+
dtype,
370+
usm_type=self.usm_type,
371+
sycl_queue=self.sycl_queue_normalized,
372+
)
373+
for k in range(len(size)):
374+
step = key[k].step
375+
start = key[k].start
376+
stop = key[k].stop
377+
if start is None:
378+
start = 0
379+
if step is None:
380+
step = 1
381+
if isinstance(step, complex):
382+
step = int(abs(step))
383+
if step != 1:
384+
step = (stop - start) / float(step - 1)
385+
nn[k] = nn[k] * step + start
386+
if self.sparse:
387+
slobj = [dpnp.newaxis] * len(size)
388+
for k in range(len(size)):
389+
slobj[k] = slice(None, None)
390+
nn[k] = nn[k][tuple(slobj)]
391+
slobj[k] = dpnp.newaxis
392+
return nn

dpnp/dpnp_iface_arraycreation.py

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
dpnp_geomspace,
5353
dpnp_linspace,
5454
dpnp_logspace,
55+
dpnp_nd_grid,
5556
)
5657

5758
__all__ = [
@@ -1452,6 +1453,24 @@ class MGridClass:
14521453
14531454
For full documentation refer to :obj:`numpy.mgrid`.
14541455
1456+
Parameters
1457+
----------
1458+
device : {None, string, SyclDevice, SyclQueue}, optional
1459+
An array API concept of device where the output array is created.
1460+
The `device` can be ``None`` (the default), an OneAPI filter selector string,
1461+
an instance of :class:`dpctl.SyclDevice` corresponding to a non-partitioned SYCL device,
1462+
an instance of :class:`dpctl.SyclQueue`, or a `Device` object returned by
1463+
:obj:`dpnp.dpnp_array.dpnp_array.device` property.
1464+
usm_type : {"device", "shared", "host"}, optional
1465+
The type of SYCL USM allocation for the output array.
1466+
sycl_queue : {None, SyclQueue}, optional
1467+
A SYCL queue to use for output array allocation and copying.
1468+
1469+
Returns
1470+
-------
1471+
out : one dpnp.ndarray or tuple of dpnp.ndarray
1472+
Returns one array of grid indices, grid.shape = (len(dimensions),) + tuple(dimensions).
1473+
14551474
Examples
14561475
--------
14571476
>>> import dpnp as np
@@ -1466,13 +1485,31 @@ class MGridClass:
14661485
[0, 1, 2, 3, 4],
14671486
[0, 1, 2, 3, 4],
14681487
[0, 1, 2, 3, 4]]])
1469-
>>> np.mgrid[-1:1:5j]
1488+
1489+
>>> x = np.mgrid[-1:1:5j]
1490+
>>> x
14701491
array([-1. , -0.5, 0. , 0.5, 1. ])
1492+
>>> x.usm_type
1493+
'device'
1494+
1495+
>>> y = np.mgrid(usm_type="host")[-1:1:5j]
1496+
>>> y
1497+
array([-1. , -0.5, 0. , 0.5, 1. ])
1498+
>>> x.usm_type
1499+
'host'
14711500
14721501
"""
14731502

14741503
def __getitem__(self, key):
1475-
return dpnp.array(numpy.mgrid[key])
1504+
return dpnp_nd_grid(sparse=False)[key]
1505+
1506+
def __call__(self, device=None, usm_type="device", sycl_queue=None):
1507+
return dpnp_nd_grid(
1508+
sparse=False,
1509+
device=device,
1510+
usm_type=usm_type,
1511+
sycl_queue=sycl_queue,
1512+
)
14761513

14771514

14781515
mgrid = MGridClass()
@@ -1484,23 +1521,56 @@ class OGridClass:
14841521
14851522
For full documentation refer to :obj:`numpy.ogrid`.
14861523
1524+
Parameters
1525+
----------
1526+
device : {None, string, SyclDevice, SyclQueue}, optional
1527+
An array API concept of device where the output array is created.
1528+
The `device` can be ``None`` (the default), an OneAPI filter selector string,
1529+
an instance of :class:`dpctl.SyclDevice` corresponding to a non-partitioned SYCL device,
1530+
an instance of :class:`dpctl.SyclQueue`, or a `Device` object returned by
1531+
:obj:`dpnp.dpnp_array.dpnp_array.device` property.
1532+
usm_type : {"device", "shared", "host"}, optional
1533+
The type of SYCL USM allocation for the output array.
1534+
sycl_queue : {None, SyclQueue}, optional
1535+
A SYCL queue to use for output array allocation and copying.
1536+
1537+
Returns
1538+
-------
1539+
out : one dpnp.ndarray or tuple of dpnp.ndarray
1540+
Returns a tuple of arrays, with grid[i].shape = (1, ..., 1, dimensions[i], 1, ..., 1)
1541+
with dimensions[i] in the ith place.
1542+
14871543
Examples
14881544
--------
14891545
>>> import dpnp as np
1490-
>>> from numpy import ogrid
1491-
>>> ogrid[-1:1:5j]
1492-
array([-1. , -0.5, 0. , 0.5, 1. ])
1493-
>>> ogrid[0:5,0:5]
1546+
>>> np.ogrid[0:5, 0:5]
14941547
[array([[0],
14951548
[1],
14961549
[2],
14971550
[3],
14981551
[4]]), array([[0, 1, 2, 3, 4]])]
14991552
1553+
>>> x = np.ogrid[-1:1:5j]
1554+
>>> x
1555+
array([-1. , -0.5, 0. , 0.5, 1. ])
1556+
>>> x.usm_type
1557+
'device'
1558+
1559+
>>> y = np.ogrid(usm_type="host")[-1:1:5j]
1560+
>>> y
1561+
array([-1. , -0.5, 0. , 0.5, 1. ])
1562+
>>> x.usm_type
1563+
'host'
1564+
15001565
"""
15011566

15021567
def __getitem__(self, key):
1503-
return dpnp.array(numpy.ogrid[key])
1568+
return dpnp_nd_grid(sparse=True)[key]
1569+
1570+
def __call__(self, device=None, usm_type="device", sycl_queue=None):
1571+
return dpnp_nd_grid(
1572+
sparse=True, device=device, usm_type=usm_type, sycl_queue=sycl_queue
1573+
)
15041574

15051575

15061576
ogrid = OGridClass()

0 commit comments

Comments
 (0)