diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c1b902dc886..bfb2b14172d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -104,7 +104,7 @@ repos: "--disable=redefined-builtin", "--disable=unused-wildcard-import" ] - files: '^dpnp/(dpnp_iface.*|fft|linalg)' + files: '^dpnp/(dpnp_iface.*|fft|linalg|dpnp_array)' - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks rev: v2.14.0 hooks: diff --git a/doc/reference/ndarray.rst b/doc/reference/ndarray.rst index 4f9aef8a916..0e388cf4eab 100644 --- a/doc/reference/ndarray.rst +++ b/doc/reference/ndarray.rst @@ -66,7 +66,11 @@ of the array: dpnp.ndarray.size dpnp.ndarray.itemsize dpnp.ndarray.nbytes - dpnp.ndarray.base + dpnp.ndarray.device + dpnp.ndarray.sycl_context + dpnp.ndarray.sycl_device + dpnp.ndarray.sycl_queue + dpnp.ndarray.usm_type Data type @@ -98,6 +102,17 @@ Other attributes dpnp.ndarray.flat +Special attributes +------------------ + +.. autosummary:: + :toctree: generated/ + :nosignatures: + + dpnp.ndarray.__sycl_usm_array_interface__ + dpnp.ndarray.__usm_ndarray__ + + Array methods ------------- @@ -145,6 +160,7 @@ Array conversion dpnp.ndarray.getfield dpnp.ndarray.setflags dpnp.ndarray.fill + dpnp.ndarray.get_array Shape manipulation @@ -371,7 +387,10 @@ Basic customization: dpnp.ndarray.__new__ dpnp.ndarray.__array__ + dpnp.ndarray.__array_namespace__ dpnp.ndarray.__array_wrap__ + dpnp.ndarray.__dlpack__ + dpnp.ndarray.__dlpack_device__ Container customization: (see :ref:`Indexing `) @@ -380,12 +399,13 @@ Container customization: (see :ref:`Indexing `) :nosignatures: dpnp.ndarray.__len__ + dpnp.ndarray.__iter__ dpnp.ndarray.__getitem__ dpnp.ndarray.__setitem__ dpnp.ndarray.__contains__ -Conversion; the operations :class:`int() `, -:class:`float() ` and :class:`complex() `. +Conversion; the operations :class:`int() `, :class:`float() `, +:class:`complex() ` and :func:`operator.index() `. They work only on arrays that have one element in them and return the appropriate scalar. @@ -393,6 +413,7 @@ and return the appropriate scalar. :toctree: generated/ :nosignatures: + dpnp.ndarray.__index__ dpnp.ndarray.__int__ dpnp.ndarray.__float__ dpnp.ndarray.__complex__ diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index 48df4acf3b8..bba114c5a59 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -24,6 +24,15 @@ # THE POSSIBILITY OF SUCH DAMAGE. # ***************************************************************************** +""" +Interface of an ndarray representing a multidimensional tensor of numeric +elements stored in a USM allocation on a SYCL device. + +""" + +# pylint: disable=invalid-name +# pylint: disable=protected-access + import dpctl.tensor as dpt from dpctl.tensor._numpy_helper import AxisError @@ -34,8 +43,8 @@ def _get_unwrapped_index_key(key): """ Get an unwrapped index key. - Return a key where each nested instance of DPNP array is unwrapped into USM ndarray - for further processing in DPCTL advanced indexing functions. + Return a key where each nested instance of DPNP array is unwrapped into + USM ndarray for further processing in DPCTL advanced indexing functions. """ @@ -50,15 +59,18 @@ def _get_unwrapped_index_key(key): return key +# pylint: disable=too-many-public-methods class dpnp_array: """ - Multi-dimensional array object. + An array object represents a multidimensional tensor of numeric elements + stored in a USM allocation on a SYCL device. - This is a wrapper around dpctl.tensor.usm_ndarray that provides + This is a wrapper around :class:`dpctl.tensor.usm_ndarray` that provides methods to be compliant with original NumPy. """ + # pylint: disable=too-many-positional-arguments def __init__( self, shape, @@ -97,95 +109,28 @@ def __init__( array_namespace=dpnp, ) - @property - def __sycl_usm_array_interface__(self): - return self._array_obj.__sycl_usm_array_interface__ - - def get_array(self): - """Get usm_ndarray object.""" - return self._array_obj - - @property - def T(self): - """View of the transposed array.""" - return self.transpose() - - @property - def mT(self): - """ - View of the matrix transposed array. - - The matrix transpose is the transpose of the last two dimensions, even - if the array is of higher dimension. - - Raises - ------ - ValueError - If the array is of dimension less than 2. - - Examples - -------- - >>> import dpnp as np - >>> a = np.array([[1, 2], [3, 4]]) - >>> a - array([[1, 2], - [3, 4]]) - >>> a.mT - array([[1, 3], - [2, 4]]) - - >>> a = np.arange(8).reshape((2, 2, 2)) - >>> a - array([[[0, 1], - [2, 3]], - [[4, 5], - [6, 7]]]) - >>> a.mT - array([[[0, 2], - [1, 3]], - [[4, 6], - [5, 7]]]) - - """ - - if self.ndim < 2: - raise ValueError("matrix transpose with ndim < 2 is undefined") - - return dpnp_array._create_from_usm_ndarray(self._array_obj.mT) - - @property - def sycl_queue(self): - return self._array_obj.sycl_queue - - @property - def sycl_device(self): - return self._array_obj.sycl_device - - @property - def sycl_context(self): - return self._array_obj.sycl_context - - @property - def device(self): - return self._array_obj.device - - @property - def usm_type(self): - return self._array_obj.usm_type - def __abs__(self): - r"""Return ``\|self\|``.""" + """Return :math:`|self|`.""" return dpnp.abs(self) def __add__(self, other): - """Return ``self+value``.""" + """Return :math:`self+value`.""" return dpnp.add(self, other) def __and__(self, other): - """Return ``self&value``.""" + """Return :math:`self&value`.""" return dpnp.bitwise_and(self, other) def __array__(self, dtype=None, /, *, copy=None): + """ + NumPy's array protocol method to disallow implicit conversion. + + Without this definition, ``numpy.asarray(dpnp_arr)`` converts + :class:`dpnp.ndarray` instance into NumPy array with data type `object` + and every element being zero-dimensional :class:`dpnp.ndarray`. + + """ # noqa: D403 + raise TypeError( "Implicit conversion to a NumPy array is not allowed. " "Please use `.asnumpy()` to construct a NumPy array explicitly." @@ -194,13 +139,6 @@ def __array__(self, dtype=None, /, *, copy=None): # '__array_finalize__', # '__array_function__', # '__array_interface__', - # '__array_prepare__', - # '__array_priority__', - # '__array_struct__', - - __array_ufunc__ = None - - # '__array_wrap__', def __array_namespace__(self, /, *, api_version=None): """ @@ -212,6 +150,7 @@ def __array_namespace__(self, /, *, api_version=None): Request namespace compliant with given version of array API. If ``None``, namespace for the most recent supported version is returned. + Default: ``None``. Returns @@ -227,6 +166,14 @@ def __array_namespace__(self, /, *, api_version=None): return self._array_obj.__array_namespace__(api_version=api_version) + # '__array_prepare__', + # '__array_priority__', + # '__array_struct__', + + __array_ufunc__ = None + + # '__array_wrap__', + def __bool__(self): """``True`` if self else ``False``.""" return self._array_obj.__bool__() @@ -235,13 +182,15 @@ def __bool__(self): # `__class_getitem__`, def __complex__(self): + """Convert a zero-dimensional array to a Python complex object.""" return self._array_obj.__complex__() # '__contains__', def __copy__(self): """ - Used if :func:`copy.copy` is called on an array. Returns a copy of the array. + Used if :func:`copy.copy` is called on an array. Returns a copy of the + array. Equivalent to ``a.copy(order="K")``. @@ -253,7 +202,6 @@ def __copy__(self): # '__delitem__', # '__dir__', # '__divmod__', - # '__doc__', def __dlpack__( self, *, stream=None, max_version=None, dl_device=None, copy=None @@ -266,12 +214,14 @@ def __dlpack__( stream : {:class:`dpctl.SyclQueue`, None}, optional Execution queue to synchronize with. If ``None``, synchronization is not performed. + Default: ``None``. max_version {tuple of ints, None}, optional The maximum DLPack version the consumer (caller of ``__dlpack__``) supports. As ``__dlpack__`` may not always return a DLPack capsule with version `max_version`, the consumer must verify the version even if this argument is passed. + Default: ``None``. dl_device {tuple, None}, optional: The device the returned DLPack capsule will be placed on. The @@ -279,6 +229,7 @@ def __dlpack__( ``__dlpack_device__`` method, an integer enumerator representing the device type followed by an integer representing the index of the device. + Default: ``None``. copy {bool, None}, optional: Boolean indicating whether or not to copy the input. @@ -329,27 +280,30 @@ def __dlpack_device__(self): return self._array_obj.__dlpack_device__() + # '__doc__', + def __eq__(self, other): - """Return ``self==value``.""" + """Return :math:`self==value`.""" return dpnp.equal(self, other) def __float__(self): + """Convert a zero-dimensional array to a Python float object.""" return self._array_obj.__float__() def __floordiv__(self, other): - """Return ``self//value``.""" + """Return :math:`self//value`.""" return dpnp.floor_divide(self, other) # '__format__', def __ge__(self, other): - """Return ``self>=value``.""" + """Return :math:`self>=value`.""" return dpnp.greater_equal(self, other) # '__getattribute__', def __getitem__(self, key): - """Return ``self[key]``.""" + """Return :math:`self[key]`.""" key = _get_unwrapped_index_key(key) item = self._array_obj.__getitem__(key) @@ -358,41 +312,39 @@ def __getitem__(self, key): # '__getstate__', def __gt__(self, other): - """Return ``self>value``.""" + """Return :math:`self>value`.""" return dpnp.greater(self, other) # '__hash__', def __iadd__(self, other): - """Return ``self+=value``.""" + """Return :math:`self+=value`:math:.""" dpnp.add(self, other, out=self) return self def __iand__(self, other): - """Return ``self&=value``.""" + """Return :math:`self&=value`:math:.""" dpnp.bitwise_and(self, other, out=self) return self def __ifloordiv__(self, other): - """Return ``self//=value``.""" + """Return :math:`self//=value`.""" dpnp.floor_divide(self, other, out=self) return self def __ilshift__(self, other): - """Return ``self<<=value``.""" + """Return :math:`self<<=value`.""" dpnp.left_shift(self, other, out=self) return self def __imatmul__(self, other): - """Return ``self@=value``.""" + """Return :math:`self@=value`.""" - """ - Unlike `matmul(a, b, out=a)` we ensure that the result is not broadcast - if the result without `out` would have less dimensions than `a`. - Since the signature of matmul is '(n?,k),(k,m?)->(n?,m?)' this is the - case exactly when the second operand has both core dimensions. - We have to enforce this check by passing the correct `axes=`. - """ + # Unlike `matmul(a, b, out=a)` we ensure that the result isn't broadcast + # if the result without `out` would have less dimensions than `a`. + # Since the signature of matmul is '(n?,k),(k,m?)->(n?,m?)' this is the + # case exactly when the second operand has both core dimensions. + # We have to enforce this check by passing the correct `axes=`. if self.ndim == 1: axes = [(-1,), (-2, -1), (-1,)] else: @@ -400,130 +352,132 @@ def __imatmul__(self, other): try: dpnp.matmul(self, other, out=self, dtype=self.dtype, axes=axes) - except AxisError: + except AxisError as e: # AxisError should indicate that the axes argument didn't work out # which should mean the second operand not being 2 dimensional. raise ValueError( "inplace matrix multiplication requires the first operand to " "have at least one and the second at least two dimensions." - ) + ) from e return self def __imod__(self, other): - """Return ``self%=value``.""" + """Return :math:`self%=value`.""" dpnp.remainder(self, other, out=self) return self def __imul__(self, other): - """Return ``self*=value``.""" + """Return :math:`self*=value`.""" dpnp.multiply(self, other, out=self) return self def __index__(self): + """Convert a zero-dimensional array to a Python int object.""" return self._array_obj.__index__() # '__init__', # '__init_subclass__', def __int__(self): + """Convert a zero-dimensional array to a Python int object.""" return self._array_obj.__int__() def __invert__(self): - """Return ``~self``.""" + """Return :math:`~self`.""" return dpnp.invert(self) def __ior__(self, other): - """Return ``self|=value``.""" + """Return :math:`self|=value`.""" dpnp.bitwise_or(self, other, out=self) return self def __ipow__(self, other): - """Return ``self**=value``.""" + """Return :math:`self**=value`.""" dpnp.power(self, other, out=self) return self def __irshift__(self, other): - """Return ``self>>=value``.""" + """Return :math:`self>>=value`.""" dpnp.right_shift(self, other, out=self) return self def __isub__(self, other): - """Return ``self-=value``.""" + """Return :math:`self-=value`.""" dpnp.subtract(self, other, out=self) return self def __iter__(self): - """Return ``iter(self)``.""" + """Return :math:`iter(self)`.""" if self.ndim == 0: raise TypeError("iteration over a 0-d array") return (self[i] for i in range(self.shape[0])) def __itruediv__(self, other): - """Return ``self/=value``.""" + """Return :math:`self/=value`.""" dpnp.true_divide(self, other, out=self) return self def __ixor__(self, other): - """Return ``self^=value``.""" + """Return :math:`self^=value`.""" dpnp.bitwise_xor(self, other, out=self) return self def __le__(self, other): - """Return ``self<=value``.""" + """Return :math:`self<=value`.""" return dpnp.less_equal(self, other) def __len__(self): - """Return ``len(self)``.""" + """Return :math:`len(self)`.""" return self._array_obj.__len__() def __lshift__(self, other): - """Return ``self<>self``.""" + """Return :math:`value>>self`.""" return dpnp.right_shift(other, self) def __rshift__(self, other): - """Return ``self>>value``.""" + """Return :math:`self>>value`.""" return dpnp.right_shift(self, other) def __rsub__(self, other): - """Return ``value-self``.""" + """Return :math:`value-self`.""" return dpnp.subtract(other, self) def __rtruediv__(self, other): - """Return ``value/self``.""" + """Return :math:`value/self`.""" return dpnp.true_divide(other, self) def __rxor__(self, other): - """Return ``value^self``.""" + """Return :math:`value^self`.""" return dpnp.bitwise_xor(other, self) # '__setattr__', @@ -599,17 +553,25 @@ def __setitem__(self, key, val): __slots__ = ("_array_obj",) def __str__(self): - """Return ``str(self)``.""" + """Return :math:`str(self)`.""" return self._array_obj.__str__() def __sub__(self, other): - """Return ``self-value``.""" + """Return :math:`self-value`.""" return dpnp.subtract(self, other) # '__subclasshook__', + @property + def __sycl_usm_array_interface__(self): + """ + Give ``__sycl_usm_array_interface__`` dictionary describing the array. + + """ # noqa: D200 + return self._array_obj.__sycl_usm_array_interface__ + def __truediv__(self, other): - """Return ``self/value``.""" + """Return :math:`self/value`.""" return dpnp.true_divide(self, other) @property @@ -621,9 +583,9 @@ def __usm_ndarray__(self): corresponding to the content of the object. This property is intended to speed-up conversion from - :class:`dpnp.ndarray` to :class:`dpctl.tensor.usm_ndarray` passed - into `dpctl.tensor.asarray` function. The input object that implements - `__usm_ndarray__` protocol is recognized as owner of USM allocation + :class:`dpnp.ndarray` to :class:`dpctl.tensor.usm_ndarray` passed into + :func:`dpctl.tensor.asarray` function. The input object that implements + ``__usm_ndarray__`` protocol is recognized as owner of USM allocation that is managed by a smart pointer, and asynchronous deallocation will not involve GIL. @@ -632,11 +594,17 @@ def __usm_ndarray__(self): return self._array_obj def __xor__(self, other): - """Return ``self^value``.""" + """Return :math:`self^value`.""" return dpnp.bitwise_xor(self, other) @staticmethod def _create_from_usm_ndarray(usm_ary: dpt.usm_ndarray): + """ + Return :class:`dpnp.ndarray` instance from USM allocation providing + by an instance of :class:`dpctl.tensor.usm_ndarray`. + + """ + if not isinstance(usm_ary, dpt.usm_ndarray): raise TypeError( f"Expected dpctl.tensor.usm_ndarray, got {type(usm_ary)}" @@ -648,7 +616,7 @@ def _create_from_usm_ndarray(usm_ary: dpt.usm_ndarray): def all(self, axis=None, out=None, keepdims=False, *, where=True): """ - Returns True if all elements evaluate to True. + Returns ``True`` if all elements evaluate to ``True.`` Refer to :obj:`dpnp.all` for full documentation. @@ -664,7 +632,7 @@ def all(self, axis=None, out=None, keepdims=False, *, where=True): def any(self, axis=None, out=None, keepdims=False, *, where=True): """ - Returns True if any of the elements of `a` evaluate to True. + Returns ``True`` if any of the elements of `a` evaluate to ``True``. Refer to :obj:`dpnp.any` for full documentation. @@ -704,7 +672,8 @@ def argsort( self, axis=-1, kind=None, order=None, *, descending=False, stable=None ): """ - Return an ndarray of indices that sort the array along the specified axis. + Return an ndarray of indices that sort the array along the specified + axis. Refer to :obj:`dpnp.argsort` for full documentation. @@ -714,22 +683,26 @@ def argsort( Axis along which to sort. If ``None``, the array is flattened before sorting. The default is ``-1``, which sorts along the last axis. + Default: ``-1``. kind : {None, "stable", "mergesort", "radixsort"}, optional Sorting algorithm. The default is ``None``, which uses parallel merge-sort or parallel radix-sort algorithms depending on the array data type. + Default: ``None``. descending : bool, optional Sort order. If ``True``, the array must be sorted in descending order (by value). If ``False``, the array must be sorted in ascending order (by value). + Default: ``False``. stable : {None, bool}, optional Sort stability. If ``True``, the returned array will maintain the relative order of `a` values which compare as equal. The same behavior applies when set to ``False`` or ``None``. Internally, this option selects ``kind="stable"``. + Default: ``None``. See Also @@ -814,8 +787,8 @@ def astype( Specifies whether to copy an array when the specified dtype matches the data type of that array. If ``True``, a newly allocated array must always be returned. If ``False`` and the specified dtype - matches the data type of that array, the self array must be returned; - otherwise, a newly allocated array must be returned. + matches the data type of that array, the self array must be + returned; otherwise, a newly allocated array must be returned. Default: ``True``. device : {None, string, SyclDevice, SyclQueue, Device}, optional @@ -865,7 +838,8 @@ def astype( def choose(self, /, choices, out=None, mode="wrap"): """ - Use an array as index array to construct a new array from a set of choices. + Use an array as index array to construct a new array from a set of + choices. Refer to :obj:`dpnp.choose` for full documentation. @@ -900,10 +874,7 @@ def conj(self): """ - if not dpnp.issubdtype(self.dtype, dpnp.complexfloating): - return self - else: - return dpnp.conjugate(self) + return self.conjugate() def conjugate(self): """ @@ -915,8 +886,7 @@ def conjugate(self): if not dpnp.issubdtype(self.dtype, dpnp.complexfloating): return self - else: - return dpnp.conjugate(self) + return dpnp.conjugate(self) def copy(self, order="C", device=None, usm_type=None, sycl_queue=None): """ @@ -928,6 +898,7 @@ def copy(self, order="C", device=None, usm_type=None, sycl_queue=None): ---------- order : {None, "C", "F", "A", "K"}, optional Memory layout of the newly output array. + Default: ``"C"``. device : {None, string, SyclDevice, SyclQueue, Device}, optional An array API concept of device where the output array is created. @@ -940,12 +911,14 @@ def copy(self, order="C", device=None, usm_type=None, sycl_queue=None): Default: ``None``. usm_type : {None, "device", "shared", "host"}, optional The type of SYCL USM allocation for the output array. + Default: ``None``. sycl_queue : {None, SyclQueue}, optional A SYCL queue to use for output array allocation and copying. The `sycl_queue` can be passed as ``None`` (the default), which means to get the SYCL queue from `device` keyword if present or to use a default queue. + Default: ``None``. Returns @@ -1016,6 +989,28 @@ def cumsum(self, axis=None, dtype=None, out=None): # 'data', + @property + def device(self): + """ + Return :class:`dpctl.tensor.Device` object representing residence of + the array data. + + The ``Device`` object represents Array API notion of the device, and + contains :class:`dpctl.SyclQueue` associated with this array. Hence, + ``.device`` property provides information distinct from ``.sycl_device`` + property. + + Examples + -------- + >>> import dpnp as np + >>> x = np.ones(10) + >>> x.device + Device(level_zero:gpu:0) + + """ + + return self._array_obj.device + def diagonal(self, offset=0, axis1=0, axis2=1): """ Return specified diagonals. @@ -1063,7 +1058,10 @@ def dot(self, b, out=None): @property def dtype(self): - """Returns NumPy's dtype corresponding to the type of the array elements.""" + """ + Returns NumPy's dtype corresponding to the type of the array elements. + + """ # noqa: D200 return self._array_obj.dtype @@ -1096,6 +1094,7 @@ def fill(self, value): """ # lazy import avoids circular imports + # pylint: disable=import-outside-toplevel from .dpnp_algo.dpnp_fill import dpnp_fill dpnp_fill(self, value) @@ -1108,7 +1107,10 @@ def flags(self): @property def flat(self): - """Return a flat iterator, or set a flattened version of self to value.""" + """ + Return a flat iterator, or set a flattened version of self to value. + + """ # noqa: D200 return dpnp.flatiter(self) @@ -1156,6 +1158,10 @@ def flatten(self, order="C"): return self.reshape(-1, order=order, copy=True) + def get_array(self): + """Get :class:`dpctl.tensor.usm_ndarray` object.""" + return self._array_obj + # 'getfield', @property @@ -1193,6 +1199,7 @@ def imag(self, value): array([1.+9.j, 3.+9.j, 5.+9.j]) """ + if dpnp.issubdtype(self.dtype, dpnp.complexfloating): dpnp.copyto(self._array_obj.imag, value) else: @@ -1218,7 +1225,8 @@ def item(self, *args): Returns ------- out : Standard Python scalar object - A copy of the specified element of the array as a suitable Python scalar. + A copy of the specified element of the array as a suitable Python + scalar. Examples -------- @@ -1314,6 +1322,49 @@ def min( where=where, ) + @property + def mT(self): + """ + View of the matrix transposed array. + + The matrix transpose is the transpose of the last two dimensions, even + if the array is of higher dimension. + + Raises + ------ + ValueError + If the array is of dimension less than ``2``. + + Examples + -------- + >>> import dpnp as np + >>> a = np.array([[1, 2], [3, 4]]) + >>> a + array([[1, 2], + [3, 4]]) + >>> a.mT + array([[1, 3], + [2, 4]]) + + >>> a = np.arange(8).reshape((2, 2, 2)) + >>> a + array([[[0, 1], + [2, 3]], + [[4, 5], + [6, 7]]]) + >>> a.mT + array([[[0, 2], + [1, 3]], + [[4, 6], + [5, 7]]]) + + """ + + if self.ndim < 2: + raise ValueError("matrix transpose with ndim < 2 is undefined") + + return dpnp_array._create_from_usm_ndarray(self._array_obj.mT) + @property def nbytes(self): """Total bytes consumed by the elements of the array.""" @@ -1510,7 +1561,8 @@ def reshape(self, *shape, order="C", copy=None): Notes ----- Unlike the free function `dpnp.reshape`, this method on `ndarray` allows - the elements of the shape parameter to be passed in as separate arguments. + the elements of the shape parameter to be passed in as separate + arguments. For example, ``a.reshape(10, 11)`` is equivalent to ``a.reshape((10, 11))``. @@ -1658,22 +1710,26 @@ def sort( axis : int, optional Axis along which to sort. The default is ``-1``, which sorts along the last axis. + Default: ``-1``. kind : {None, "stable", "mergesort", "radixsort"}, optional Sorting algorithm. The default is ``None``, which uses parallel merge-sort or parallel radix-sort algorithms depending on the array data type. + Default: ``None``. descending : bool, optional Sort order. If ``True``, the array must be sorted in descending order (by value). If ``False``, the array must be sorted in ascending order (by value). + Default: ``False``. stable : {None, bool}, optional Sort stability. If ``True``, the returned array will maintain the relative order of `a` values which compare as equal. The same behavior applies when set to ``False`` or ``None``. Internally, this option selects ``kind="stable"``. + Default: ``None``. See Also @@ -1810,6 +1866,63 @@ def swapaxes(self, axis1, axis2): return dpnp.swapaxes(self, axis1=axis1, axis2=axis2) + @property + def sycl_context(self): + """ + Return :class:`dpctl.SyclContext` object to which USM data is bound. + + """ # noqa: D200 + return self._array_obj.sycl_context + + @property + def sycl_device(self): + """ + Return :class:`dpctl.SyclDevice` object on which USM data was + allocated. + + """ + return self._array_obj.sycl_device + + @property + def sycl_queue(self): + """ + Return :class:`dpctl.SyclQueue` object associated with USM data. + + """ # noqa: D200 + return self._array_obj.sycl_queue + + @property + def T(self): + """ + View of the transposed array. + + Same as ``self.transpose()``. + + See Also + -------- + :obj:`dpnp.transpose` : Equivalent function. + + Examples + -------- + >>> import dpnp as np + >>> a = np.array([[1, 2], [3, 4]]) + >>> a + array([[1, 2], + [3, 4]]) + >>> a.T + array([[1, 3], + [2, 4]]) + + >>> a = np.array([1, 2, 3, 4]) + >>> a + array([1, 2, 3, 4]) + >>> a.T + array([1, 2, 3, 4]) + + """ + + return self.transpose() + def take(self, indices, axis=None, out=None, mode="wrap"): """ Take elements from an array along an axis. @@ -1836,6 +1949,7 @@ def to_device(self, device, /, *, stream=None): stream : {SyclQueue, None}, optional Execution queue to synchronize with. If ``None``, synchronization is not performed. + Default: ``None``. Returns @@ -1904,8 +2018,10 @@ def transpose(self, *axes): See Also -------- :obj:`dpnp.transpose` : Equivalent function. - :obj:`dpnp.ndarray.ndarray.T` : Array property returning the array transposed. - :obj:`dpnp.ndarray.reshape` : Give a new shape to an array without changing its data. + :obj:`dpnp.ndarray.ndarray.T` : Array property returning the array + transposed. + :obj:`dpnp.ndarray.reshape` : Give a new shape to an array without + changing its data. Examples -------- @@ -1979,5 +2095,23 @@ def var( correction=correction, ) + # 'view' -# 'view' + @property + def usm_type(self): + """ + USM type of underlying memory. Possible values are: + + * ``"device"`` + USM-device allocation in device memory, only accessible to kernels + executed on the device + * ``"shared"`` + USM-shared allocation in device memory, accessible both from the + device and from the host + * ``"host"`` + USM-host allocation in host memory, accessible both from the device + and from the host + + """ + + return self._array_obj.usm_type