• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IntelPython / dpnp / 11124403837

01 Oct 2024 11:30AM UTC coverage: 59.488% (-0.02%) from 59.509%
11124403837

push

github

web-flow
Enable dpnp tests with NumPy 2.0 in public CI (#2009)

3754 of 9430 branches covered (39.81%)

Branch coverage included in aggregate %.

13754 of 20001 relevant lines covered (68.77%)

16848.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.23
/dpnp/dpnp_iface_manipulation.py
1
# -*- coding: utf-8 -*-
2
# *****************************************************************************
3
# Copyright (c) 2016-2024, Intel Corporation
4
# All rights reserved.
5
#
6
# Redistribution and use in source and binary forms, with or without
7
# modification, are permitted provided that the following conditions are met:
8
# - Redistributions of source code must retain the above copyright notice,
9
#   this list of conditions and the following disclaimer.
10
# - Redistributions in binary form must reproduce the above copyright notice,
11
#   this list of conditions and the following disclaimer in the documentation
12
#   and/or other materials provided with the distribution.
13
#
14
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24
# THE POSSIBILITY OF SUCH DAMAGE.
25
# *****************************************************************************
26

27
"""
28
Interface of the Array manipulation routines part of the DPNP
29

30
Notes
31
-----
32
This module is a face or public interface file for the library
33
it contains:
34
 - Interface functions
35
 - documentation for the functions
36
 - The functions parameters check
37

38
"""
39

40

41
import math
1✔
42
import operator
1✔
43

44
import dpctl.tensor as dpt
1✔
45
import numpy
1✔
46
from dpctl.tensor._numpy_helper import AxisError, normalize_axis_index
1✔
47

48
import dpnp
1✔
49

50
from .dpnp_array import dpnp_array
1✔
51

52
__all__ = [
1✔
53
    "append",
54
    "array_split",
55
    "asarray_chkfinite",
56
    "asfarray",
57
    "atleast_1d",
58
    "atleast_2d",
59
    "atleast_3d",
60
    "broadcast_arrays",
61
    "broadcast_to",
62
    "can_cast",
63
    "column_stack",
64
    "concat",
65
    "concatenate",
66
    "copyto",
67
    "dsplit",
68
    "dstack",
69
    "expand_dims",
70
    "flip",
71
    "fliplr",
72
    "flipud",
73
    "hsplit",
74
    "hstack",
75
    "moveaxis",
76
    "ndim",
77
    "permute_dims",
78
    "ravel",
79
    "repeat",
80
    "require",
81
    "reshape",
82
    "resize",
83
    "result_type",
84
    "roll",
85
    "rollaxis",
86
    "rot90",
87
    "row_stack",
88
    "shape",
89
    "size",
90
    "split",
91
    "squeeze",
92
    "stack",
93
    "swapaxes",
94
    "tile",
95
    "transpose",
96
    "trim_zeros",
97
    "unique",
98
    "vsplit",
99
    "vstack",
100
]
101

102

103
def _check_stack_arrays(arrays):
1✔
104
    """Validate a sequence type of arrays to stack."""
105

106
    if not hasattr(arrays, "__getitem__"):
1✔
107
        raise TypeError(
1✔
108
            'arrays to stack must be passed as a "sequence" type '
109
            "such as list or tuple."
110
        )
111

112

113
def _unique_1d(
1✔
114
    ar,
115
    return_index=False,
116
    return_inverse=False,
117
    return_counts=False,
118
    equal_nan=True,
119
):
120
    """Find the unique elements of a 1D array."""
121

122
    def _get_first_nan_index(usm_a):
1✔
123
        """
124
        Find the first index of NaN in the input array with at least two NaNs.
125

126
        Assume the input array sorted where the NaNs are always at the end.
127
        Return None if the input array does not have at least two NaN values or
128
        data type of the array is not inexact.
129

130
        """
131

132
        if (
1✔
133
            usm_a.size > 2
134
            and dpnp.issubdtype(usm_a.dtype, dpnp.inexact)
135
            and dpnp.isnan(usm_a[-2])
136
        ):
137
            if dpnp.issubdtype(usm_a.dtype, dpnp.complexfloating):
1✔
138
                # for complex all NaNs are considered equivalent
139
                true_val = dpt.asarray(
1✔
140
                    True, sycl_queue=usm_a.sycl_queue, usm_type=usm_a.usm_type
141
                )
142
                return dpt.searchsorted(dpt.isnan(usm_a), true_val, side="left")
1✔
143
            return dpt.searchsorted(usm_a, usm_a[-1], side="left")
1✔
144
        return None
1✔
145

146
    usm_ar = dpnp.get_usm_ndarray(ar)
1✔
147

148
    num_of_flags = (return_index, return_inverse, return_counts).count(True)
1✔
149
    if num_of_flags == 0:
1✔
150
        usm_res = dpt.unique_values(usm_ar)
1✔
151
        usm_res = (usm_res,)  # cast to a tuple to align with other cases
1✔
152
    elif num_of_flags == 1 and return_inverse:
1✔
153
        usm_res = dpt.unique_inverse(usm_ar)
1✔
154
    elif num_of_flags == 1 and return_counts:
1✔
155
        usm_res = dpt.unique_counts(usm_ar)
1✔
156
    else:
157
        usm_res = dpt.unique_all(usm_ar)
1✔
158

159
    first_nan = None
1✔
160
    if equal_nan:
1✔
161
        first_nan = _get_first_nan_index(usm_res[0])
1✔
162

163
    # collapse multiple NaN values in an array into one NaN value if applicable
164
    result = (
1✔
165
        usm_res[0][: first_nan + 1] if first_nan is not None else usm_res[0],
166
    )
167
    if return_index:
1✔
168
        result += (
1✔
169
            (
170
                usm_res.indices[: first_nan + 1]
171
                if first_nan is not None
172
                else usm_res.indices
173
            ),
174
        )
175
    if return_inverse:
1✔
176
        if first_nan is not None:
1✔
177
            # all NaNs are collapsed, so need to replace the indices with
178
            # the index of the first NaN value in result array of unique values
179
            dpt.place(
1✔
180
                usm_res.inverse_indices,
181
                usm_res.inverse_indices > first_nan,
182
                dpt.reshape(first_nan, 1),
183
            )
184

185
        result += (usm_res.inverse_indices,)
1✔
186
    if return_counts:
1✔
187
        if first_nan is not None:
1✔
188
            # all NaNs are collapsed, so need to put a count of all NaNs
189
            # at the last index
190
            dpt.sum(usm_res.counts[first_nan:], out=usm_res.counts[first_nan])
1✔
191
            result += (usm_res.counts[: first_nan + 1],)
1✔
192
        else:
193
            result += (usm_res.counts,)
1✔
194

195
    result = tuple(dpnp_array._create_from_usm_ndarray(x) for x in result)
1✔
196
    return _unpack_tuple(result)
1✔
197

198

199
def _unique_build_sort_indices(a, index_sh):
1✔
200
    """
201
    Build the indices of an input array (when axis is provided) which result
202
    in the unique array.
203

204
    """
205

206
    is_inexact = dpnp.issubdtype(a, dpnp.inexact)
1✔
207
    if dpnp.issubdtype(a.dtype, numpy.unsignedinteger):
1✔
208
        ar_cmp = a.astype(dpnp.intp)
1✔
209
    elif dpnp.issubdtype(a.dtype, dpnp.bool):
1✔
210
        ar_cmp = a.astype(numpy.int8)
1✔
211
    else:
212
        ar_cmp = a
1✔
213

214
    def compare_axis_elems(idx1, idx2):
1✔
215
        comp = dpnp.trim_zeros(ar_cmp[idx1] - ar_cmp[idx2], "f")
1✔
216
        if comp.shape[0] > 0:
1✔
217
            diff = comp[0]
1✔
218
            if is_inexact and dpnp.isnan(diff):
1✔
219
                isnan1 = dpnp.isnan(ar_cmp[idx1])
1✔
220
                if not isnan1.any():  # no NaN in ar_cmp[idx1]
1✔
221
                    return True  # ar_cmp[idx1] goes to left
1✔
222

223
                isnan2 = dpnp.isnan(ar_cmp[idx2])
1✔
224
                if not isnan2.any():  # no NaN in ar_cmp[idx2]
1✔
225
                    return False  # ar_cmp[idx1] goes to right
1✔
226

227
                # for complex all NaNs are considered equivalent
228
                if (isnan1 & isnan2).all():  # NaNs at the same places
1✔
229
                    return False  # ar_cmp[idx1] goes to right
1✔
230

231
                xor_nan_idx = dpnp.where(isnan1 ^ isnan2)[0]
1✔
232
                if xor_nan_idx.size == 0:
1✔
233
                    return False
1✔
234

235
                if dpnp.isnan(ar_cmp[idx2][xor_nan_idx[0]]):
1✔
236
                    # first NaN in XOR mask is from ar_cmp[idx2]
237
                    return True  # ar_cmp[idx1] goes to left
1✔
238
                return False
1✔
239
            return diff < 0
1✔
240
        return False
1✔
241

242
    # sort the array `a` lexicographically using the first item
243
    # of each element on the axis
244
    sorted_indices = dpnp.empty_like(a, shape=index_sh, dtype=dpnp.intp)
1✔
245
    queue = [(numpy.arange(0, index_sh, dtype=numpy.intp).tolist(), 0)]
1✔
246
    while len(queue) != 0:
1✔
247
        current, off = queue.pop(0)
1✔
248
        if len(current) == 0:
1✔
249
            continue
1✔
250

251
        mid_elem = current[0]
1✔
252
        left = []
1✔
253
        right = []
1✔
254
        for i in range(1, len(current)):
1✔
255
            if compare_axis_elems(current[i], mid_elem):
1✔
256
                left.append(current[i])
1✔
257
            else:
258
                right.append(current[i])
1✔
259

260
        elem_pos = off + len(left)
1✔
261
        queue.append((left, off))
1✔
262
        queue.append((right, elem_pos + 1))
1✔
263

264
        sorted_indices[elem_pos] = mid_elem
1✔
265
    return sorted_indices
1✔
266

267

268
def _unpack_tuple(a):
1✔
269
    """Unpacks one-element tuples for use as return values."""
270

271
    if len(a) == 1:
1✔
272
        return a[0]
1✔
273
    return a
1✔
274

275

276
def append(arr, values, axis=None):
1✔
277
    """
278
    Append values to the end of an array.
279

280
    For full documentation refer to :obj:`numpy.append`.
281

282
    Parameters
283
    ----------
284
    arr : {dpnp.ndarray, usm_ndarray}
285
        Values are appended to a copy of this array.
286
    values : {scalar, array_like}
287
        These values are appended to a copy of `arr`. It must be of the
288
        correct shape (the same shape as `arr`, excluding `axis`). If
289
        `axis` is not specified, `values` can be any shape and will be
290
        flattened before use.
291
        These values can be in any form that can be converted to an array.
292
        This includes scalars, lists, lists of tuples, tuples,
293
        tuples of tuples, tuples of lists, and ndarrays.
294
    axis : {None, int}, optional
295
        The axis along which `values` are appended. If `axis` is not
296
        given, both `arr` and `values` are flattened before use.
297
        Default: ``None``.
298

299
    Returns
300
    -------
301
    out : dpnp.ndarray
302
        A copy of `arr` with `values` appended to `axis`. Note that
303
        `append` does not occur in-place: a new array is allocated and
304
        filled. If `axis` is ``None``, `out` is a flattened array.
305

306
    See Also
307
    --------
308
    :obj:`dpnp.insert` : Insert elements into an array.
309
    :obj:`dpnp.delete` : Delete elements from an array.
310

311
    Examples
312
    --------
313
    >>> import dpnp as np
314
    >>> a = np.array([1, 2, 3])
315
    >>> np.append(a, [[4, 5, 6], [7, 8, 9]])
316
    array([1, 2, 3, 4, 5, 6, 7, 8, 9])
317

318
    When `axis` is specified, `values` must have the correct shape.
319

320
    >>> b = np.array([[1, 2, 3], [4, 5, 6]])
321
    >>> np.append(b, [[7, 8, 9]], axis=0)
322
    array([[1, 2, 3],
323
           [4, 5, 6],
324
           [7, 8, 9]])
325
    >>> np.append(b, [7, 8, 9], axis=0)
326
    Traceback (most recent call last):
327
        ...
328
    ValueError: all the input arrays must have same number of dimensions, but
329
    the array at index 0 has 2 dimension(s) and the array at index 1 has 1
330
    dimension(s)
331

332
    """
333

334
    dpnp.check_supported_arrays_type(arr)
1✔
335
    if not dpnp.is_supported_array_type(values):
1✔
336
        values = dpnp.array(
1✔
337
            values, usm_type=arr.usm_type, sycl_queue=arr.sycl_queue
338
        )
339

340
    if axis is None:
1✔
341
        if arr.ndim != 1:
1✔
342
            arr = dpnp.ravel(arr)
1✔
343
        if values.ndim != 1:
1✔
344
            values = dpnp.ravel(values)
1✔
345
        axis = 0
1✔
346
    return dpnp.concatenate((arr, values), axis=axis)
1✔
347

348

349
def array_split(ary, indices_or_sections, axis=0):
1✔
350
    """
351
    Split an array into multiple sub-arrays.
352

353
    Please refer to the :obj:`dpnp.split` documentation. The only difference
354
    between these functions is that ``dpnp.array_split`` allows
355
    `indices_or_sections` to be an integer that does *not* equally divide the
356
    axis. For an array of length l that should be split into n sections, it
357
    returns ``l % n`` sub-arrays of size ``l//n + 1`` and the rest of size
358
    ``l//n``.
359

360
    For full documentation refer to :obj:`numpy.array_split`.
361

362
    Parameters
363
    ----------
364
    ary : {dpnp.ndarray, usm_ndarray}
365
        Array to be divided into sub-arrays.
366
    indices_or_sections : {int, sequence of ints}
367
        If `indices_or_sections` is an integer, N, and array length is l, it
368
        returns ``l % n`` sub-arrays of size ``l//n + 1`` and the rest of size
369
        ``l//n``.
370

371
        If `indices_or_sections` is a sequence of sorted integers, the entries
372
        indicate where along `axis` the array is split.
373
    axis : int, optional
374
        The axis along which to split.
375
        Default: ``0``.
376

377
    Returns
378
    -------
379
    sub-arrays : list of dpnp.ndarray
380
        A list of sub arrays. Each array is a view of the corresponding input
381
        array.
382

383
    See Also
384
    --------
385
    :obj:`dpnp.split` : Split array into multiple sub-arrays of equal size.
386

387
    Examples
388
    --------
389
    >>> import dpnp as np
390
    >>> x = np.arange(8.0)
391
    >>> np.array_split(x, 3)
392
    [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7.])]
393

394
    >>> x = np.arange(9)
395
    >>> np.array_split(x, 4)
396
    [array([0, 1, 2]), array([3, 4]), array([5, 6]), array([7, 8])]
397

398
    """
399

400
    dpnp.check_supported_arrays_type(ary)
1✔
401
    n_tot = ary.shape[axis]
1✔
402
    try:
1✔
403
        # handle array case.
404
        n_sec = len(indices_or_sections) + 1
1✔
405
        div_points = [0] + list(indices_or_sections) + [n_tot]
1✔
406
    except TypeError:
1✔
407
        # indices_or_sections is a scalar, not an array.
408
        n_sec = int(indices_or_sections)
1✔
409
        if n_sec <= 0:
1✔
410
            raise ValueError("number sections must be larger than 0.") from None
1✔
411
        n_each_sec, extras = numpy.divmod(n_tot, n_sec)
1✔
412
        section_sizes = (
1✔
413
            [0] + extras * [n_each_sec + 1] + (n_sec - extras) * [n_each_sec]
414
        )
415
        div_points = dpnp.array(
1✔
416
            section_sizes,
417
            dtype=dpnp.intp,
418
            usm_type=ary.usm_type,
419
            sycl_queue=ary.sycl_queue,
420
        ).cumsum()
421

422
    sub_arys = []
1✔
423
    sary = dpnp.swapaxes(ary, axis, 0)
1✔
424
    for i in range(n_sec):
1✔
425
        st = div_points[i]
1✔
426
        end = div_points[i + 1]
1✔
427
        sub_arys.append(dpnp.swapaxes(sary[st:end], axis, 0))
1✔
428

429
    return sub_arys
1✔
430

431

432
def asarray_chkfinite(
1✔
433
    a, dtype=None, order=None, *, device=None, usm_type=None, sycl_queue=None
434
):
435
    """
436
    Convert the input to an array, checking for NaNs or Infs.
437

438
    For full documentation refer to :obj:`numpy.asarray_chkfinite`.
439

440
    Parameters
441
    ----------
442
    arr : array_like
443
        Input data, in any form that can be converted to an array. This
444
        includes lists, lists of tuples, tuples, tuples of tuples, tuples
445
        of lists and ndarrays. Success requires no NaNs or Infs.
446
    dtype : {None, str, dtype object}, optional
447
        By default, the data-type is inferred from the input data.
448
        Default: ``None``.
449
    order : {None, "C", "F", "A", "K"}, optional
450
        Memory layout of the newly output array.
451
        Default: ``"K"``.
452
    device : {None, string, SyclDevice, SyclQueue}, optional
453
        An array API concept of device where the output array is created.
454
        The `device` can be ``None`` (the default), an OneAPI filter selector
455
        string, an instance of :class:`dpctl.SyclDevice` corresponding to
456
        a non-partitioned SYCL device, an instance of :class:`dpctl.SyclQueue`,
457
        or a `Device` object returned by
458
        :obj:`dpnp.dpnp_array.dpnp_array.device` property.
459
        Default: ``None``.
460
    usm_type : {None, "device", "shared", "host"}, optional
461
        The type of SYCL USM allocation for the output array.
462
        Default: ``None``.
463
    sycl_queue : {None, SyclQueue}, optional
464
        A SYCL queue to use for output array allocation and copying. The
465
        `sycl_queue` can be passed as ``None`` (the default), which means
466
        to get the SYCL queue from `device` keyword if present or to use
467
        a default queue.
468
        Default: ``None``.
469

470
    Returns
471
    -------
472
    out : dpnp.ndarray
473
        Array interpretation of `a`. No copy is performed if the input is
474
        already an ndarray.
475

476
    Raises
477
    -------
478
    ValueError
479
        Raises ``ValueError`` if `a` contains NaN (Not a Number) or
480
        Inf (Infinity).
481

482
    See Also
483
    --------
484
    :obj:`dpnp.asarray` : Create an array.
485
    :obj:`dpnp.asanyarray` : Converts an input object into array.
486
    :obj:`dpnp.ascontiguousarray` : Convert input to a c-contiguous array.
487
    :obj:`dpnp.asfortranarray` : Convert input to an array with column-major
488
                        memory order.
489
    :obj:`dpnp.fromiter` : Create an array from an iterator.
490
    :obj:`dpnp.fromfunction` : Construct an array by executing a function
491
                        on grid positions.
492

493
    Examples
494
    --------
495
    >>> import dpnp as np
496

497
    Convert a list into an array. If all elements are finite,
498
    ``asarray_chkfinite`` is identical to ``asarray``.
499

500
    >>> a = [1, 2]
501
    >>> np.asarray_chkfinite(a, dtype=np.float32)
502
    array([1., 2.])
503

504
    Raises ``ValueError`` if array_like contains NaNs or Infs.
505

506
    >>> a = [1, 2, np.inf]
507
    >>> try:
508
    ...     np.asarray_chkfinite(a)
509
    ... except ValueError:
510
    ...     print('ValueError')
511
    ValueError
512

513
    Creating an array on a different device or with a specified usm_type
514

515
    >>> x = np.asarray_chkfinite([1, 2, 3]) # default case
516
    >>> x, x.device, x.usm_type
517
    (array([1, 2, 3]), Device(level_zero:gpu:0), 'device')
518

519
    >>> y = np.asarray_chkfinite([1, 2, 3], device="cpu")
520
    >>> y, y.device, y.usm_type
521
    (array([1, 2, 3]), Device(opencl:cpu:0), 'device')
522

523
    >>> z = np.asarray_chkfinite([1, 2, 3], usm_type="host")
524
    >>> z, z.device, z.usm_type
525
    (array([1, 2, 3]), Device(level_zero:gpu:0), 'host')
526

527
    """
528

529
    a = dpnp.asarray(
1✔
530
        a,
531
        dtype=dtype,
532
        order=order,
533
        device=device,
534
        usm_type=usm_type,
535
        sycl_queue=sycl_queue,
536
    )
537
    if dpnp.issubdtype(a.dtype, dpnp.inexact) and not dpnp.isfinite(a).all():
1✔
538
        raise ValueError("array must not contain infs or NaNs")
1✔
539
    return a
1✔
540

541

542
def asfarray(a, dtype=None, *, device=None, usm_type=None, sycl_queue=None):
1✔
543
    """
544
    Return an array converted to a float type.
545

546
    For full documentation refer to :obj:`numpy.asfarray`.
547

548
    Parameters
549
    ----------
550
    a : array_like
551
        Input data, in any form that can be converted to an array.
552
        This includes an instance of :class:`dpnp.ndarray` or
553
        :class:`dpctl.tensor.usm_ndarray`, an object representing
554
        SYCL USM allocation and implementing `__sycl_usm_array_interface__`
555
        protocol, an instance of :class:`numpy.ndarray`, an object supporting
556
        Python buffer protocol, a Python scalar, or a (possibly nested)
557
        sequence of Python scalars.
558
    dtype : str or dtype object, optional
559
        Float type code to coerce input array `a`.  If `dtype` is ``None``,
560
        :obj:`dpnp.bool` or one of the `int` dtypes, it is replaced with
561
        the default floating type (:obj:`dpnp.float64` if a device supports it,
562
        or :obj:`dpnp.float32` type otherwise).
563
    device : {None, string, SyclDevice, SyclQueue}, optional
564
        An array API concept of device where the output array is created.
565
        The `device` can be ``None`` (the default), an OneAPI filter selector
566
        string, an instance of :class:`dpctl.SyclDevice` corresponding to
567
        a non-partitioned SYCL device, an instance of :class:`dpctl.SyclQueue`,
568
        or a `Device` object returned by :obj:`dpnp.ndarray.device` property.
569
    usm_type : {None, "device", "shared", "host"}, optional
570
        The type of SYCL USM allocation for the output array.
571
    sycl_queue : {None, SyclQueue}, optional
572
        A SYCL queue to use for output array allocation and copying. The
573
        `sycl_queue` can be passed as ``None`` (the default), which means
574
        to get the SYCL queue from `device` keyword if present or to use
575
        a default queue.
576
        Default: ``None``.
577

578
    Returns
579
    -------
580
    out : dpnp.ndarray
581
        The input `a` as a float ndarray.
582

583
    Examples
584
    --------
585
    >>> import dpnp as np
586
    >>> np.asfarray([2, 3])
587
    array([2.,  3.])
588
    >>> np.asfarray([2, 3], dtype=dpnp.float32)
589
    array([2., 3.], dtype=float32)
590
    >>> np.asfarray([2, 3], dtype=dpnp.int32)
591
    array([2.,  3.])
592

593
    """
594

595
    _sycl_queue = dpnp.get_normalized_queue_device(
×
596
        a, sycl_queue=sycl_queue, device=device
597
    )
598

599
    if dtype is None or not dpnp.issubdtype(dtype, dpnp.inexact):
×
600
        dtype = dpnp.default_float_type(sycl_queue=_sycl_queue)
×
601

602
    return dpnp.asarray(
×
603
        a, dtype=dtype, usm_type=usm_type, sycl_queue=_sycl_queue
604
    )
605

606

607
def atleast_1d(*arys):
1✔
608
    """
609
    Convert inputs to arrays with at least one dimension.
610

611
    For full documentation refer to :obj:`numpy.atleast_1d`.
612

613
    Parameters
614
    ----------
615
    arys : {dpnp.ndarray, usm_ndarray}
616
        One or more array-like sequences. Arrays that already have one or more
617
        dimensions are preserved.
618

619
    Returns
620
    -------
621
    out : dpnp.ndarray
622
        An array, or list of arrays, each with ``a.ndim >= 1``.
623
        Copies are made only if necessary.
624

625
    See Also
626
    --------
627
    :obj:`dpnp.atleast_2d` : View inputs as arrays with at least two dimensions.
628
    :obj:`dpnp.atleast_3d` : View inputs as arrays with at least three
629
                             dimensions.
630

631
    Examples
632
    --------
633
    >>> import dpnp as np
634
    >>> x = np.array(1.0)
635
    >>> np.atleast_1d(x)
636
    array([1.])
637

638
    >>> y = np.array([3, 4])
639
    >>> np.atleast_1d(x, y)
640
    [array([1.]), array([3, 4])]
641

642
    >>> x = np.arange(9.0).reshape(3,3)
643
    >>> np.atleast_1d(x)
644
    array([[0., 1., 2.],
645
           [3., 4., 5.],
646
           [6., 7., 8.]])
647
    >>> np.atleast_1d(x) is x
648
    True
649

650
    """
651

652
    res = []
1✔
653
    dpnp.check_supported_arrays_type(*arys)
1✔
654
    for ary in arys:
1✔
655
        if ary.ndim == 0:
1✔
656
            result = ary.reshape(1)
1✔
657
        else:
658
            result = ary
1✔
659
        if isinstance(result, dpt.usm_ndarray):
1✔
660
            result = dpnp_array._create_from_usm_ndarray(result)
1✔
661
        res.append(result)
1✔
662
    if len(res) == 1:
1✔
663
        return res[0]
1✔
664
    return res
1✔
665

666

667
def atleast_2d(*arys):
1✔
668
    """
669
    View inputs as arrays with at least two dimensions.
670

671
    For full documentation refer to :obj:`numpy.atleast_2d`.
672

673
    Parameters
674
    ----------
675
    arys : {dpnp.ndarray, usm_ndarray}
676
        One or more array-like sequences. Arrays that already have two or more
677
        dimensions are preserved.
678

679
    Returns
680
    -------
681
    out : dpnp.ndarray
682
        An array, or list of arrays, each with ``a.ndim >= 2``.
683
        Copies are avoided where possible, and views with two or more
684
        dimensions are returned.
685

686
    See Also
687
    --------
688
    :obj:`dpnp.atleast_1d` : Convert inputs to arrays with at least one
689
                             dimension.
690
    :obj:`dpnp.atleast_3d` : View inputs as arrays with at least three
691
                             dimensions.
692

693
    Examples
694
    --------
695
    >>> import dpnp as np
696
    >>> x = np.array(3.0)
697
    >>> np.atleast_2d(x)
698
    array([[3.]])
699

700
    >>> x = np.arange(3.0)
701
    >>> np.atleast_2d(x)
702
    array([[0., 1., 2.]])
703

704
    """
705

706
    res = []
1✔
707
    dpnp.check_supported_arrays_type(*arys)
1✔
708
    for ary in arys:
1✔
709
        if ary.ndim == 0:
1✔
710
            result = ary.reshape(1, 1)
1✔
711
        elif ary.ndim == 1:
1✔
712
            result = ary[dpnp.newaxis, :]
1✔
713
        else:
714
            result = ary
1✔
715
        if isinstance(result, dpt.usm_ndarray):
1✔
716
            result = dpnp_array._create_from_usm_ndarray(result)
1✔
717
        res.append(result)
1✔
718
    if len(res) == 1:
1✔
719
        return res[0]
1✔
720
    return res
1✔
721

722

723
def atleast_3d(*arys):
1✔
724
    """
725
    View inputs as arrays with at least three dimensions.
726

727
    For full documentation refer to :obj:`numpy.atleast_3d`.
728

729
    Parameters
730
    ----------
731
    arys : {dpnp.ndarray, usm_ndarray}
732
        One or more array-like sequences. Arrays that already have three or more
733
        dimensions are preserved.
734

735
    Returns
736
    -------
737
    out : dpnp.ndarray
738
        An array, or list of arrays, each with ``a.ndim >= 3``. Copies are
739
        avoided where possible, and views with three or more dimensions are
740
        returned.
741

742
    See Also
743
    --------
744
    :obj:`dpnp.atleast_1d` : Convert inputs to arrays with at least one
745
                             dimension.
746
    :obj:`dpnp.atleast_2d` : View inputs as arrays with at least three
747
                             dimensions.
748

749
    Examples
750
    --------
751
    >>> import dpnp as np
752
    >>> x = np.array(3.0)
753
    >>> np.atleast_3d(x)
754
    array([[[3.]]])
755

756
    >>> x = np.arange(3.0)
757
    >>> np.atleast_3d(x).shape
758
    (1, 3, 1)
759

760
    >>> x = np.arange(12.0).reshape(4, 3)
761
    >>> np.atleast_3d(x).shape
762
    (4, 3, 1)
763

764
    """
765

766
    res = []
1✔
767
    dpnp.check_supported_arrays_type(*arys)
1✔
768
    for ary in arys:
1✔
769
        if ary.ndim == 0:
1✔
770
            result = ary.reshape(1, 1, 1)
1✔
771
        elif ary.ndim == 1:
1✔
772
            result = ary[dpnp.newaxis, :, dpnp.newaxis]
1✔
773
        elif ary.ndim == 2:
1✔
774
            result = ary[:, :, dpnp.newaxis]
1✔
775
        else:
776
            result = ary
1✔
777
        if isinstance(result, dpt.usm_ndarray):
1✔
778
            result = dpnp_array._create_from_usm_ndarray(result)
1✔
779
        res.append(result)
1✔
780
    if len(res) == 1:
1✔
781
        return res[0]
1✔
782
    return res
1✔
783

784

785
def broadcast_arrays(*args, subok=False):
1✔
786
    """
787
    Broadcast any number of arrays against each other.
788

789
    For full documentation refer to :obj:`numpy.broadcast_arrays`.
790

791
    Parameters
792
    ----------
793
    args : {dpnp.ndarray, usm_ndarray}
794
        A list of arrays to broadcast.
795

796
    Returns
797
    -------
798
    out : list of dpnp.ndarray
799
        A list of arrays which are views on the original arrays from `args`.
800

801
    Limitations
802
    -----------
803
    Parameter `subok` is supported with default value.
804
    Otherwise ``NotImplementedError`` exception will be raised.
805

806
    See Also
807
    --------
808
    :obj:`dpnp.broadcast_to` : Broadcast an array to a new shape.
809

810
    Examples
811
    --------
812
    >>> import dpnp as np
813
    >>> x = np.array([[1, 2, 3]])
814
    >>> y = np.array([[4], [5]])
815
    >>> np.broadcast_arrays(x, y)
816
    [array([[1, 2, 3],
817
            [1, 2, 3]]), array([[4, 4, 4],
818
            [5, 5, 5]])]
819

820
    """
821

822
    if subok is not False:
1✔
823
        raise NotImplementedError(f"subok={subok} is currently not supported")
1✔
824

825
    if len(args) == 0:
1✔
826
        return []
1✔
827

828
    usm_arrays = dpt.broadcast_arrays(*[dpnp.get_usm_ndarray(a) for a in args])
1✔
829
    return [dpnp_array._create_from_usm_ndarray(a) for a in usm_arrays]
1✔
830

831

832
# pylint: disable=redefined-outer-name
833
def broadcast_to(array, /, shape, subok=False):
1✔
834
    """
835
    Broadcast an array to a new shape.
836

837
    For full documentation refer to :obj:`numpy.broadcast_to`.
838

839
    Parameters
840
    ----------
841
    array : {dpnp.ndarray, usm_ndarray}
842
        The array to broadcast.
843
    shape : tuple or int
844
        The shape of the desired array. A single integer ``i`` is interpreted
845
        as ``(i,)``.
846

847
    Returns
848
    -------
849
    out : dpnp.ndarray
850
        An array having a specified shape.
851
        Must have the same data type as `array`.
852

853
    Limitations
854
    -----------
855
    Parameter `subok` is supported with default value.
856
    Otherwise ``NotImplementedError`` exception will be raised.
857

858
    See Also
859
    --------
860
    :obj:`dpnp.broadcast_arrays` : Broadcast any number of arrays against
861
                                   each other.
862

863
    Examples
864
    --------
865
    >>> import dpnp as np
866
    >>> x = np.array([1, 2, 3])
867
    >>> np.broadcast_to(x, (3, 3))
868
    array([[1, 2, 3],
869
           [1, 2, 3],
870
           [1, 2, 3]])
871

872
    """
873

874
    if subok is not False:
1!
875
        raise NotImplementedError(f"subok={subok} is currently not supported")
×
876

877
    usm_array = dpnp.get_usm_ndarray(array)
1✔
878
    new_array = dpt.broadcast_to(usm_array, shape)
1✔
879
    return dpnp_array._create_from_usm_ndarray(new_array)
1✔
880

881

882
def can_cast(from_, to, casting="safe"):
1✔
883
    """
884
    Returns ``True`` if cast between data types can occur according
885
    to the casting rule.
886

887
    For full documentation refer to :obj:`numpy.can_cast`.
888

889
    Parameters
890
    ----------
891
    from_ : {dpnp.ndarray, usm_ndarray, dtype, dtype specifier}
892
        Source data type.
893
    to : dtype
894
        Target data type.
895
    casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
896
        Controls what kind of data casting may occur.
897

898
    Returns
899
    -------
900
    out: bool
901
        ``True`` if cast can occur according to the casting rule,
902
        ``False`` otherwise.
903

904
    See Also
905
    --------
906
    :obj:`dpnp.result_type` : Returns the type that results from applying
907
                              the NumPy type promotion rules to the arguments.
908

909
    Examples
910
    --------
911
    Basic examples
912

913
    >>> import dpnp as np
914
    >>> np.can_cast(np.int32, np.int64)
915
    True
916
    >>> np.can_cast(np.float64, complex)
917
    True
918
    >>> np.can_cast(complex, float)
919
    False
920

921
    >>> np.can_cast('i8', 'f8')
922
    True
923
    >>> np.can_cast('i8', 'f4')
924
    False
925

926
    Array scalar checks the value, array does not
927

928
    >>> np.can_cast(np.array(1000.0), np.float32)
929
    True
930
    >>> np.can_cast(np.array([1000.0]), np.float32)
931
    False
932

933
    Using the casting rules
934

935
    >>> np.can_cast('i8', 'i8', 'no')
936
    True
937
    >>> np.can_cast('<i8', '>i8', 'no')
938
    False
939

940
    >>> np.can_cast('<i8', '>i8', 'equiv')
941
    True
942
    >>> np.can_cast('<i4', '>i8', 'equiv')
943
    False
944

945
    >>> np.can_cast('<i4', '>i8', 'safe')
946
    True
947
    >>> np.can_cast('<i8', '>i4', 'safe')
948
    False
949

950
    >>> np.can_cast('<i8', '>i4', 'same_kind')
951
    True
952
    >>> np.can_cast('<i8', '>u4', 'same_kind')
953
    False
954

955
    >>> np.can_cast('<i8', '>u4', 'unsafe')
956
    True
957

958
    """
959

960
    if dpnp.is_supported_array_type(to):
1✔
961
        raise TypeError("Cannot construct a dtype from an array")
1✔
962

963
    dtype_from = (
1✔
964
        from_.dtype
965
        if dpnp.is_supported_array_type(from_)
966
        else dpnp.dtype(from_)
967
    )
968
    return dpt.can_cast(dtype_from, to, casting=casting)
1✔
969

970

971
def column_stack(tup):
1✔
972
    """
973
    Stacks 1-D and 2-D arrays as columns into a 2-D array.
974

975
    Take a sequence of 1-D arrays and stack them as columns to make a single
976
    2-D array. 2-D arrays are stacked as-is, just like with :obj:`dpnp.hstack`.
977
    1-D arrays are turned into 2-D columns first.
978

979
    For full documentation refer to :obj:`numpy.column_stack`.
980

981
    Parameters
982
    ----------
983
    tup : {dpnp.ndarray, usm_ndarray}
984
        A sequence of 1-D or 2-D arrays to stack. All of them must have
985
        the same first dimension.
986

987
    Returns
988
    -------
989
    out : dpnp.ndarray
990
        The array formed by stacking the given arrays.
991

992
    See Also
993
    --------
994
    :obj:`dpnp.stack` : Join a sequence of arrays along a new axis.
995
    :obj:`dpnp.dstack` : Stack arrays in sequence depth wise (along third axis).
996
    :obj:`dpnp.hstack` : Stack arrays in sequence horizontally (column wise).
997
    :obj:`dpnp.vstack` : Stack arrays in sequence vertically (row wise).
998
    :obj:`dpnp.concatenate` : Join a sequence of arrays along an existing axis.
999

1000
    Examples
1001
    --------
1002
    >>> import dpnp as np
1003
    >>> a = np.array((1, 2, 3))
1004
    >>> b = np.array((2, 3, 4))
1005
    >>> np.column_stack((a, b))
1006
    array([[1, 2],
1007
           [2, 3],
1008
           [3, 4]])
1009

1010
    """
1011

1012
    _check_stack_arrays(tup)
1✔
1013

1014
    arrays = []
1✔
1015
    for v in tup:
1✔
1016
        dpnp.check_supported_arrays_type(v)
1✔
1017

1018
        if v.ndim == 1:
1✔
1019
            v = v[:, dpnp.newaxis]
1✔
1020
        elif v.ndim != 2:
1✔
1021
            raise ValueError(
1✔
1022
                "Only 1 or 2 dimensional arrays can be column stacked"
1023
            )
1024

1025
        arrays.append(v)
1✔
1026
    return dpnp.concatenate(arrays, axis=1)
1✔
1027

1028

1029
def concatenate(
1✔
1030
    arrays, /, *, axis=0, out=None, dtype=None, casting="same_kind"
1031
):
1032
    """
1033
    Join a sequence of arrays along an existing axis.
1034

1035
    Note that :obj:`dpnp.concat` is an alias of :obj:`dpnp.concatenate`.
1036

1037
    For full documentation refer to :obj:`numpy.concatenate`.
1038

1039
    Parameters
1040
    ----------
1041
    arrays : {Sequence of dpnp.ndarray or usm_ndarray}
1042
        The arrays must have the same shape, except in the dimension
1043
        corresponding to axis (the first, by default).
1044
    axis : int, optional
1045
        The axis along which the arrays will be joined. If axis is ``None``,
1046
        arrays are flattened before use.
1047
        Default: ``0``.
1048
    out : dpnp.ndarray, optional
1049
        If provided, the destination to place the result. The shape must be
1050
        correct, matching that of what concatenate would have returned
1051
        if no out argument were specified.
1052
    dtype : str or dtype
1053
        If provided, the destination array will have this dtype. Cannot be
1054
        provided together with `out`.
1055
    casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
1056
        Controls what kind of data casting may occur. Defaults to 'same_kind'.
1057

1058
    Returns
1059
    -------
1060
    out : dpnp.ndarray
1061
        The concatenated array.
1062

1063
    See Also
1064
    --------
1065
    :obj:`dpnp.array_split` : Split an array into multiple sub-arrays of equal
1066
                              or near-equal size.
1067
    :obj:`dpnp.split` : Split array into a list of multiple sub-arrays of equal
1068
                        size.
1069
    :obj:`dpnp.hsplit` : Split array into multiple sub-arrays horizontally
1070
                         (column wise).
1071
    :obj:`dpnp.vsplit` : Split array into multiple sub-arrays vertically
1072
                         (row wise).
1073
    :obj:`dpnp.dsplit` : Split array into multiple sub-arrays along
1074
                         the 3rd axis (depth).
1075
    :obj:`dpnp.stack` : Stack a sequence of arrays along a new axis.
1076
    :obj:`dpnp.block` : Assemble arrays from blocks.
1077
    :obj:`dpnp.hstack` : Stack arrays in sequence horizontally (column wise).
1078
    :obj:`dpnp.vstack` : Stack arrays in sequence vertically (row wise).
1079
    :obj:`dpnp.dstack` : Stack arrays in sequence depth wise
1080
                         (along third dimension).
1081
    :obj:`dpnp.column_stack` : Stack 1-D arrays as columns into a 2-D array.
1082

1083
    Examples
1084
    --------
1085
    >>> import dpnp as np
1086
    >>> a = np.array([[1, 2], [3, 4]])
1087
    >>> b = np.array([[5, 6]])
1088
    >>> np.concatenate((a, b), axis=0)
1089
    array([[1, 2],
1090
           [3, 4],
1091
           [5, 6]])
1092
    >>> np.concatenate((a, b.T), axis=1)
1093
    array([[1, 2, 5],
1094
           [3, 4, 6]])
1095
    >>> np.concatenate((a, b), axis=None)
1096
    array([1, 2, 3, 4, 5, 6])
1097

1098
    """
1099

1100
    if dtype is not None and out is not None:
1✔
1101
        raise TypeError(
1✔
1102
            "concatenate() only takes `out` or `dtype` as an argument, "
1103
            "but both were provided."
1104
        )
1105

1106
    usm_arrays = [dpnp.get_usm_ndarray(x) for x in arrays]
1✔
1107
    usm_res = dpt.concat(usm_arrays, axis=axis)
1✔
1108

1109
    res = dpnp_array._create_from_usm_ndarray(usm_res)
1✔
1110
    if dtype is not None:
1✔
1111
        res = res.astype(dtype, casting=casting, copy=False)
1✔
1112
    elif out is not None:
1✔
1113
        dpnp.copyto(out, res, casting=casting)
1✔
1114
        return out
1✔
1115
    return res
1✔
1116

1117

1118
concat = concatenate  # concat is an alias of concatenate
1✔
1119

1120

1121
def copyto(dst, src, casting="same_kind", where=True):
1✔
1122
    """
1123
    Copies values from one array to another, broadcasting as necessary.
1124

1125
    Raises a ``TypeError`` if the `casting` rule is violated, and if
1126
    `where` is provided, it selects which elements to copy.
1127

1128
    For full documentation refer to :obj:`numpy.copyto`.
1129

1130
    Parameters
1131
    ----------
1132
    dst : {dpnp.ndarray, usm_ndarray}
1133
        The array into which values are copied.
1134
    src : array_like
1135
        The array from which values are copied.
1136
    casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
1137
        Controls what kind of data casting may occur when copying.
1138
    where : {dpnp.ndarray, usm_ndarray, scalar} of bool, optional
1139
        A boolean array or a scalar which is broadcasted to match
1140
        the dimensions of `dst`, and selects elements to copy
1141
        from `src` to `dst` wherever it contains the value ``True``.
1142

1143
    Examples
1144
    --------
1145
    >>> import dpnp as np
1146
    >>> A = np.array([4, 5, 6])
1147
    >>> B = [1, 2, 3]
1148
    >>> np.copyto(A, B)
1149
    >>> A
1150
    array([1, 2, 3])
1151

1152
    >>> A = np.array([[1, 2, 3], [4, 5, 6]])
1153
    >>> B = [[4, 5, 6], [7, 8, 9]]
1154
    >>> np.copyto(A, B)
1155
    >>> A
1156
    array([[4, 5, 6],
1157
           [7, 8, 9]])
1158

1159
    """
1160

1161
    if not dpnp.is_supported_array_type(dst):
1✔
1162
        raise TypeError(
1✔
1163
            "Destination array must be any of supported type, "
1164
            f"but got {type(dst)}"
1165
        )
1166
    if not dpnp.is_supported_array_type(src):
1✔
1167
        src = dpnp.array(src, sycl_queue=dst.sycl_queue)
1✔
1168

1169
    if not dpnp.can_cast(src.dtype, dst.dtype, casting=casting):
1✔
1170
        raise TypeError(
1✔
1171
            f"Cannot cast from {src.dtype} to {dst.dtype} "
1172
            f"according to the rule {casting}."
1173
        )
1174

1175
    if where is True:
1✔
1176
        dst[...] = src
1✔
1177
    elif where is False:
1✔
1178
        # nothing to copy
1179
        pass
1✔
1180
    else:
1181
        if dpnp.isscalar(where):
1✔
1182
            where = dpnp.array(
1✔
1183
                where, dtype=dpnp.bool, sycl_queue=dst.sycl_queue
1184
            )
1185
        elif not dpnp.is_supported_array_type(where):
1✔
1186
            raise TypeError(
1✔
1187
                "`where` array must be any of supported type, "
1188
                f"but got {type(where)}"
1189
            )
1190
        elif where.dtype != dpnp.bool:
1✔
1191
            raise TypeError(
1✔
1192
                "`where` keyword argument must be of boolean type, "
1193
                f"but got {where.dtype}"
1194
            )
1195

1196
        dst_usm, src_usm, mask_usm = dpt.broadcast_arrays(
1✔
1197
            dpnp.get_usm_ndarray(dst),
1198
            dpnp.get_usm_ndarray(src),
1199
            dpnp.get_usm_ndarray(where),
1200
        )
1201
        dst_usm[mask_usm] = src_usm[mask_usm]
1✔
1202

1203

1204
def dsplit(ary, indices_or_sections):
1✔
1205
    """
1206
    Split array into multiple sub-arrays along the 3rd axis (depth).
1207

1208
    Please refer to the :obj:`dpnp.split` documentation. ``dsplit``
1209
    is equivalent to ``split`` with ``axis=2``, the array is always
1210
    split along the third axis provided the array dimension is greater than
1211
    or equal to 3.
1212

1213
    For full documentation refer to :obj:`numpy.dsplit`.
1214

1215
    Parameters
1216
    ----------
1217
    ary : {dpnp.ndarray, usm_ndarray}
1218
        Array to be divided into sub-arrays.
1219
    indices_or_sections : {int, sequence of ints}
1220
        If `indices_or_sections` is an integer, N, the array will be divided
1221
        into N equal arrays along the third axis. If such a split is not
1222
        possible, an error is raised.
1223
        If `indices_or_sections` is a sequence of sorted integers, the entries
1224
        indicate where along the third axis the array is split.
1225

1226
    Returns
1227
    -------
1228
    sub-arrays : list of dpnp.ndarray
1229
        A list of sub arrays. Each array is a view of the corresponding input
1230
        array.
1231

1232
    See Also
1233
    --------
1234
    :obj:`dpnp.split` : Split array into multiple sub-arrays of equal size.
1235

1236
    Examples
1237
    --------
1238
    >>> import dpnp as np
1239
    >>> x = np.arange(16.0).reshape(2, 2, 4)
1240
    >>> x
1241
    array([[[ 0.,  1.,  2.,  3.],
1242
            [ 4.,  5.,  6.,  7.]],
1243
           [[ 8.,  9., 10., 11.],
1244
            [12., 13., 14., 15.]]])
1245
    >>> np.dsplit(x, 2)
1246
    [array([[[ 0.,  1.],
1247
             [ 4.,  5.]],
1248
            [[ 8.,  9.],
1249
             [12., 13.]]]),
1250
     array([[[ 2.,  3.],
1251
             [ 6.,  7.]],
1252
            [[10., 11.],
1253
             [14., 15.]]])]
1254
    >>> np.dsplit(x, np.array([3, 6]))
1255
    [array([[[ 0.,  1.,  2.],
1256
             [ 4.,  5.,  6.]],
1257
            [[ 8.,  9., 10.],
1258
             [12., 13., 14.]]]),
1259
     array([[[ 3.],
1260
             [ 7.]],
1261
            [[11.],
1262
             [15.]]]),
1263
     array([])]
1264

1265
    """
1266

1267
    dpnp.check_supported_arrays_type(ary)
1✔
1268
    if ary.ndim < 3:
1✔
1269
        raise ValueError("dsplit only works on arrays of 3 or more dimensions")
1✔
1270
    return split(ary, indices_or_sections, 2)
1✔
1271

1272

1273
def dstack(tup):
1✔
1274
    """
1275
    Stack arrays in sequence depth wise (along third axis).
1276

1277
    This is equivalent to concatenation along the third axis after 2-D arrays
1278
    of shape `(M, N)` have been reshaped to `(M, N, 1)` and 1-D arrays of shape
1279
    `(N,)` have been reshaped to `(1, N, 1)`. Rebuilds arrays divided by
1280
    :obj:`dpnp.dsplit`.
1281

1282
    For full documentation refer to :obj:`numpy.dstack`.
1283

1284
    Parameters
1285
    ----------
1286
    tup : {dpnp.ndarray, usm_ndarray}
1287
        One or more array-like sequences. The arrays must have the same shape
1288
        along all but the third axis. 1-D or 2-D arrays must have the same
1289
        shape.
1290

1291
    Returns
1292
    -------
1293
    out : dpnp.ndarray
1294
        The array formed by stacking the given arrays, will be at least 3-D.
1295

1296
    See Also
1297
    --------
1298
    :obj:`dpnp.concatenate` : Join a sequence of arrays along an existing axis.
1299
    :obj:`dpnp.vstack` : Stack arrays in sequence vertically (row wise).
1300
    :obj:`dpnp.hstack` : Stack arrays in sequence horizontally (column wise).
1301
    :obj:`dpnp.column_stack` : Stack 1-D arrays as columns into a 2-D array.
1302
    :obj:`dpnp.stack` : Join a sequence of arrays along a new axis.
1303
    :obj:`dpnp.block` : Assemble an ndarray from nested lists of blocks.
1304
    :obj:`dpnp.dsplit` : Split array along third axis.
1305

1306
    Examples
1307
    --------
1308
    >>> import dpnp as np
1309
    >>> a = np.array((1, 2, 3))
1310
    >>> b = np.array((2, 3, 4))
1311
    >>> np.dstack((a, b))
1312
    array([[[1, 2],
1313
            [2, 3],
1314
            [3, 4]]])
1315

1316
    >>> a = np.array([[1], [2], [3]])
1317
    >>> b = np.array([[2], [3], [4]])
1318
    >>> np.dstack((a, b))
1319
    array([[[1, 2]],
1320
           [[2, 3]],
1321
           [[3, 4]]])
1322

1323
    """
1324

1325
    _check_stack_arrays(tup)
1✔
1326

1327
    arrs = atleast_3d(*tup)
1✔
1328
    if not isinstance(arrs, list):
1✔
1329
        arrs = [arrs]
1✔
1330
    return dpnp.concatenate(arrs, axis=2)
1✔
1331

1332

1333
def expand_dims(a, axis):
1✔
1334
    """
1335
    Expand the shape of an array.
1336

1337
    Insert a new axis that will appear at the `axis` position in the expanded
1338
    array shape.
1339

1340
    For full documentation refer to :obj:`numpy.expand_dims`.
1341

1342
    Parameters
1343
    ----------
1344
    a : {dpnp.ndarray, usm_ndarray}
1345
        Input array.
1346
    axis : int or tuple of ints
1347
        Position in the expanded axes where the new axis (or axes) is placed.
1348

1349
    Returns
1350
    -------
1351
    out : dpnp.ndarray
1352
        An array with the number of dimensions increased.
1353
        A view is returned whenever possible.
1354

1355
    Notes
1356
    -----
1357
    If `a` has rank (i.e, number of dimensions) `N`, a valid `axis` must reside
1358
    in the closed-interval `[-N-1, N]`.
1359
    If provided a negative `axis`, the `axis` position at which to insert a
1360
    singleton dimension is computed as `N + axis + 1`.
1361
    Hence, if provided `-1`, the resolved axis position is `N` (i.e.,
1362
    a singleton dimension must be appended to the input array `a`).
1363
    If provided `-N-1`, the resolved axis position is `0` (i.e., a
1364
    singleton dimension is added to the input array `a`).
1365

1366
    See Also
1367
    --------
1368
    :obj:`dpnp.squeeze` : The inverse operation, removing singleton dimensions
1369
    :obj:`dpnp.reshape` : Insert, remove, and combine dimensions, and resize
1370
                          existing ones
1371
    :obj:`dpnp.atleast_1d` : Convert inputs to arrays with at least one
1372
                             dimension.
1373
    :obj:`dpnp.atleast_2d` : View inputs as arrays with at least two dimensions.
1374
    :obj:`dpnp.atleast_3d` : View inputs as arrays with at least three
1375
                             dimensions.
1376

1377
    Examples
1378
    --------
1379
    >>> import dpnp as np
1380
    >>> x = np.array([1, 2])
1381
    >>> x.shape
1382
    (2,)
1383

1384
    The following is equivalent to ``x[np.newaxis, :]`` or ``x[np.newaxis]``:
1385

1386
    >>> y = np.expand_dims(x, axis=0)
1387
    >>> y
1388
    array([[1, 2]])
1389
    >>> y.shape
1390
    (1, 2)
1391

1392
    The following is equivalent to ``x[:, np.newaxis]``:
1393

1394
    >>> y = np.expand_dims(x, axis=1)
1395
    >>> y
1396
    array([[1],
1397
           [2]])
1398
    >>> y.shape
1399
    (2, 1)
1400

1401
    ``axis`` may also be a tuple:
1402

1403
    >>> y = np.expand_dims(x, axis=(0, 1))
1404
    >>> y
1405
    array([[[1, 2]]])
1406

1407
    >>> y = np.expand_dims(x, axis=(2, 0))
1408
    >>> y
1409
    array([[[1],
1410
            [2]]])
1411

1412
    Note that some examples may use ``None`` instead of ``np.newaxis``.  These
1413
    are the same objects:
1414

1415
    >>> np.newaxis is None
1416
    True
1417

1418
    """
1419

1420
    usm_a = dpnp.get_usm_ndarray(a)
1✔
1421
    usm_res = dpt.expand_dims(usm_a, axis=axis)
1✔
1422
    return dpnp_array._create_from_usm_ndarray(usm_res)
1✔
1423

1424

1425
def flip(m, axis=None):
1✔
1426
    """
1427
    Reverse the order of elements in an array along the given axis.
1428

1429
    The shape of the array is preserved, but the elements are reordered.
1430

1431
    For full documentation refer to :obj:`numpy.flip`.
1432

1433
    Parameters
1434
    ----------
1435
    m : {dpnp.ndarray, usm_ndarray}
1436
        Input array.
1437
    axis : None or int or tuple of ints, optional
1438
         Axis or axes along which to flip over. The default,
1439
         ``axis=None``, will flip over all of the axes of the input array.
1440
         If `axis` is negative it counts from the last to the first axis.
1441
         If `axis` is a tuple of integers, flipping is performed on all of
1442
         the axes specified in the tuple.
1443

1444
    Returns
1445
    -------
1446
    out : dpnp.ndarray
1447
        A view of `m` with the entries of axis reversed.
1448

1449
    See Also
1450
    --------
1451
    :obj:`dpnp.flipud` : Flip an array vertically (axis=0).
1452
    :obj:`dpnp.fliplr` : Flip an array horizontally (axis=1).
1453

1454
    Examples
1455
    --------
1456
    >>> import dpnp as np
1457
    >>> A = np.arange(8).reshape((2, 2, 2))
1458
    >>> A
1459
    array([[[0, 1],
1460
            [2, 3]],
1461
           [[4, 5],
1462
            [6, 7]]])
1463
    >>> np.flip(A, 0)
1464
    array([[[4, 5],
1465
            [6, 7]],
1466
           [[0, 1],
1467
            [2, 3]]])
1468
    >>> np.flip(A, 1)
1469
    array([[[2, 3],
1470
            [0, 1]],
1471
           [[6, 7],
1472
            [4, 5]]])
1473
    >>> np.flip(A)
1474
    array([[[7, 6],
1475
            [5, 4]],
1476
           [[3, 2],
1477
            [1, 0]]])
1478
    >>> np.flip(A, (0, 2))
1479
    array([[[5, 4],
1480
            [7, 6]],
1481
           [[1, 0],
1482
            [3, 2]]])
1483
    >>> A = np.random.randn(3, 4, 5)
1484
    >>> np.all(np.flip(A, 2) == A[:, :, ::-1, ...])
1485
    array(True)
1486

1487
    """
1488

1489
    m_usm = dpnp.get_usm_ndarray(m)
1✔
1490
    return dpnp_array._create_from_usm_ndarray(dpt.flip(m_usm, axis=axis))
1✔
1491

1492

1493
def fliplr(m):
1✔
1494
    """
1495
    Reverse the order of elements along axis 1 (left/right).
1496

1497
    For a 2-D array, this flips the entries in each row in the left/right
1498
    direction. Columns are preserved, but appear in a different order than
1499
    before.
1500

1501
    For full documentation refer to :obj:`numpy.fliplr`.
1502

1503
    Parameters
1504
    ----------
1505
    m : {dpnp.ndarray, usm_ndarray}
1506
        Input array, must be at least 2-D.
1507

1508
    Returns
1509
    -------
1510
    out : dpnp.ndarray
1511
        A view of `m` with the columns reversed.
1512

1513
    See Also
1514
    --------
1515
    :obj:`dpnp.flipud` : Flip an array vertically (axis=0).
1516
    :obj:`dpnp.flip` : Flip array in one or more dimensions.
1517
    :obj:`dpnp.rot90` : Rotate array counterclockwise.
1518

1519
    Examples
1520
    --------
1521
    >>> import dpnp as np
1522
    >>> A = np.diag(np.array([1., 2., 3.]))
1523
    >>> A
1524
    array([[1.,  0.,  0.],
1525
           [0.,  2.,  0.],
1526
           [0.,  0.,  3.]])
1527
    >>> np.fliplr(A)
1528
    array([[0.,  0.,  1.],
1529
           [0.,  2.,  0.],
1530
           [3.,  0.,  0.]])
1531

1532
    >>> A = np.random.randn(2, 3, 5)
1533
    >>> np.all(np.fliplr(A) == A[:, ::-1, ...])
1534
    array(True)
1535

1536
    """
1537

1538
    dpnp.check_supported_arrays_type(m)
1✔
1539

1540
    if m.ndim < 2:
1✔
1541
        raise ValueError(f"Input must be >= 2-d, but got {m.ndim}")
1✔
1542
    return m[:, ::-1]
1✔
1543

1544

1545
def flipud(m):
1✔
1546
    """
1547
    Reverse the order of elements along axis 0 (up/down).
1548

1549
    For a 2-D array, this flips the entries in each column in the up/down
1550
    direction. Rows are preserved, but appear in a different order than before.
1551

1552
    For full documentation refer to :obj:`numpy.flipud`.
1553

1554
    Parameters
1555
    ----------
1556
    m : {dpnp.ndarray, usm_ndarray}
1557
        Input array.
1558

1559
    Returns
1560
    -------
1561
    out : dpnp.ndarray
1562
        A view of `m` with the rows reversed.
1563

1564
    See Also
1565
    --------
1566
    :obj:`dpnp.fliplr` : Flip array in the left/right direction.
1567
    :obj:`dpnp.flip` : Flip array in one or more dimensions.
1568
    :obj:`dpnp.rot90` : Rotate array counterclockwise.
1569

1570
    Examples
1571
    --------
1572
    >>> import dpnp as np
1573
    >>> A = np.diag(np.array([1., 2., 3.]))
1574
    >>> A
1575
    array([[1.,  0.,  0.],
1576
           [0.,  2.,  0.],
1577
           [0.,  0.,  3.]])
1578
    >>> np.flipud(A)
1579
    array([[0.,  0.,  3.],
1580
           [0.,  2.,  0.],
1581
           [1.,  0.,  0.]])
1582

1583
    >>> A = np.random.randn(2, 3, 5)
1584
    >>> np.all(np.flipud(A) == A[::-1, ...])
1585
    array(True)
1586

1587
    >>> np.flipud(np.array([1, 2]))
1588
    array([2, 1])
1589

1590
    """
1591

1592
    dpnp.check_supported_arrays_type(m)
1✔
1593

1594
    if m.ndim < 1:
1✔
1595
        raise ValueError(f"Input must be >= 1-d, but got {m.ndim}")
1✔
1596
    return m[::-1, ...]
1✔
1597

1598

1599
def hsplit(ary, indices_or_sections):
1✔
1600
    """
1601
    Split an array into multiple sub-arrays horizontally (column-wise).
1602

1603
    Please refer to the :obj:`dpnp.split` documentation. ``hsplit``
1604
    is equivalent to ``dpnp.split`` with ``axis=1``, the array is always
1605
    split along the second axis except for 1-D arrays, where it is split at
1606
    ``axis=0``.
1607

1608
    For full documentation refer to :obj:`numpy.hsplit`.
1609

1610
    Parameters
1611
    ----------
1612
    ary : {dpnp.ndarray, usm_ndarray}
1613
        Array to be divided into sub-arrays.
1614
    indices_or_sections : {int, sequence of ints}
1615
        If `indices_or_sections` is an integer, N, the array will be divided
1616
        into N equal arrays along the second axis except for 1-D arrays, where
1617
        it is split at the first axis. If such a split is not possible,
1618
        an error is raised.
1619
        If `indices_or_sections` is a sequence of sorted integers, the entries
1620
        indicate where along the second axis the array is split. For 1-D arrays,
1621
        the entries indicate where along the first axis the array is split.
1622

1623
    Returns
1624
    -------
1625
    sub-arrays : list of dpnp.ndarray
1626
        A list of sub arrays. Each array is a view of the corresponding input
1627
        array.
1628

1629
    See Also
1630
    --------
1631
    :obj:`dpnp.split` : Split array into multiple sub-arrays of equal size.
1632

1633
    Examples
1634
    --------
1635
    >>> import dpnp as np
1636
    >>> x = np.arange(16.0).reshape(4, 4)
1637
    >>> x
1638
    array([[ 0.,  1.,  2.,  3.],
1639
           [ 4.,  5.,  6.,  7.],
1640
           [ 8.,  9., 10., 11.],
1641
           [12., 13., 14., 15.]])
1642
    >>> np.hsplit(x, 2)
1643
    [array([[ 0.,  1.],
1644
            [ 4.,  5.],
1645
            [ 8.,  9.],
1646
            [12., 13.]]),
1647
     array([[ 2.,  3.],
1648
            [ 6.,  7.],
1649
            [10., 11.],
1650
            [14., 15.]])]
1651
    >>> np.hsplit(x, np.array([3, 6]))
1652
    [array([[ 0.,  1.,  2.],
1653
            [ 4.,  5.,  6.],
1654
            [ 8.,  9., 10.],
1655
            [12., 13., 14.]]),
1656
     array([[ 3.],
1657
            [ 7.],
1658
            [11.],
1659
            [15.]]),
1660
     array([])]
1661

1662
    With a higher dimensional array the split is still along the second axis.
1663

1664
    >>> x = np.arange(8.0).reshape(2, 2, 2)
1665
    >>> x
1666
    array([[[0., 1.],
1667
            [2., 3.]],
1668
           [[4., 5.],
1669
            [6., 7.]]])
1670
    >>> np.hsplit(x, 2)
1671
    [array([[[0., 1.]],
1672
            [[4., 5.]]]),
1673
     array([[[2., 3.]],
1674
            [[6., 7.]]])]
1675

1676
    With a 1-D array, the split is along axis 0.
1677

1678
    >>> x = np.array([0, 1, 2, 3, 4, 5])
1679
    >>> np.hsplit(x, 2)
1680
    [array([0, 1, 2]), array([3, 4, 5])]
1681

1682
    """
1683

1684
    dpnp.check_supported_arrays_type(ary)
1✔
1685
    if ary.ndim == 0:
1✔
1686
        raise ValueError("hsplit only works on arrays of 1 or more dimensions")
1✔
1687
    if ary.ndim > 1:
1✔
1688
        return split(ary, indices_or_sections, 1)
1✔
1689
    return split(ary, indices_or_sections, 0)
1✔
1690

1691

1692
def hstack(tup, *, dtype=None, casting="same_kind"):
1✔
1693
    """
1694
    Stack arrays in sequence horizontally (column wise).
1695

1696
    For full documentation refer to :obj:`numpy.hstack`.
1697

1698
    Parameters
1699
    ----------
1700
    tup : {dpnp.ndarray, usm_ndarray}
1701
        The arrays must have the same shape along all but the second axis,
1702
        except 1-D arrays which can be any length.
1703
    dtype : str or dtype
1704
        If provided, the destination array will have this dtype.
1705
    casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
1706
        Controls what kind of data casting may occur. Defaults to 'same_kind'.
1707

1708
    Returns
1709
    -------
1710
    out : dpnp.ndarray
1711
        The stacked array which has one more dimension than the input arrays.
1712

1713
    See Also
1714
    --------
1715
    :obj:`dpnp.concatenate` : Join a sequence of arrays along an existing axis.
1716
    :obj:`dpnp.stack` : Join a sequence of arrays along a new axis.
1717
    :obj:`dpnp.vstack` : Stack arrays in sequence vertically (row wise).
1718
    :obj:`dpnp.dstack` : Stack arrays in sequence depth wise
1719
                         (along third dimension).
1720
    :obj:`dpnp.column_stack` : Stack 1-D arrays as columns into a 2-D array.
1721
    :obj:`dpnp.block` : Assemble an ndarray from nested lists of blocks.
1722
    :obj:`dpnp.split` : Split array into a list of multiple sub-arrays of equal
1723
                        size.
1724

1725
    Examples
1726
    --------
1727
    >>> import dpnp as np
1728
    >>> a = np.array((1, 2, 3))
1729
    >>> b = np.array((4, 5, 6))
1730
    >>> np.hstack((a, b))
1731
    array([1, 2, 3, 4, 5, 6])
1732

1733
    >>> a = np.array([[1], [2], [3]])
1734
    >>> b = np.array([[4], [5], [6]])
1735
    >>> np.hstack((a, b))
1736
    array([[1, 4],
1737
           [2, 5],
1738
           [3, 6]])
1739

1740
    """
1741

1742
    _check_stack_arrays(tup)
1✔
1743

1744
    arrs = dpnp.atleast_1d(*tup)
1✔
1745
    if not isinstance(arrs, list):
1✔
1746
        arrs = [arrs]
1✔
1747

1748
    # As a special case, dimension 0 of 1-dimensional arrays is "horizontal"
1749
    if arrs and arrs[0].ndim == 1:
1✔
1750
        return dpnp.concatenate(arrs, axis=0, dtype=dtype, casting=casting)
1✔
1751
    return dpnp.concatenate(arrs, axis=1, dtype=dtype, casting=casting)
1✔
1752

1753

1754
def moveaxis(a, source, destination):
1✔
1755
    """
1756
    Move axes of an array to new positions. Other axes remain in their original
1757
    order.
1758

1759
    For full documentation refer to :obj:`numpy.moveaxis`.
1760

1761
    Parameters
1762
    ----------
1763
    a : {dpnp.ndarray, usm_ndarray}
1764
        The array whose axes should be reordered.
1765
    source : int or sequence of int
1766
        Original positions of the axes to move. These must be unique.
1767
    destination : int or sequence of int
1768
        Destination positions for each of the original axes. These must also be
1769
        unique.
1770

1771
    Returns
1772
    -------
1773
    out : dpnp.ndarray
1774
        Array with moved axes. This array is a view of the input array.
1775

1776
    See Also
1777
    --------
1778
    :obj:`dpnp.transpose` : Permute the dimensions of an array.
1779
    :obj:`dpnp.swapaxes` : Interchange two axes of an array.
1780

1781
    Examples
1782
    --------
1783
    >>> import dpnp as np
1784
    >>> x = np.zeros((3, 4, 5))
1785
    >>> np.moveaxis(x, 0, -1).shape
1786
    (4, 5, 3)
1787
    >>> np.moveaxis(x, -1, 0).shape
1788
    (5, 3, 4)
1789

1790
    """
1791

1792
    usm_array = dpnp.get_usm_ndarray(a)
1✔
1793
    return dpnp_array._create_from_usm_ndarray(
1✔
1794
        dpt.moveaxis(usm_array, source, destination)
1795
    )
1796

1797

1798
def ndim(a):
1✔
1799
    """
1800
    Return the number of dimensions of array-like input.
1801

1802
    For full documentation refer to :obj:`numpy.ndim`.
1803

1804
    Parameters
1805
    ----------
1806
    a : array_like
1807
        Input data.
1808

1809
    Returns
1810
    -------
1811
    number_of_dimensions : int
1812
        The number of dimensions in `a`. Scalars are zero-dimensional.
1813

1814
    See Also
1815
    --------
1816
    :obj:`dpnp.ndarray.ndim` : Equivalent method for `dpnp.ndarray`
1817
                        or `usm_ndarray` input.
1818
    :obj:`dpnp.shape` : Return the shape of an array.
1819
    :obj:`dpnp.ndarray.shape` : Return the shape of an array.
1820

1821
    Examples
1822
    --------
1823
    >>> import dpnp as np
1824
    >>> a = [[1, 2, 3], [4, 5, 6]]
1825
    >>> np.ndim(a)
1826
    2
1827
    >>> a = np.asarray(a)
1828
    >>> np.ndim(a)
1829
    2
1830
    >>> np.ndim(1)
1831
    0
1832

1833
    """
1834

1835
    if dpnp.is_supported_array_type(a):
1✔
1836
        return a.ndim
1✔
1837
    return numpy.ndim(a)
1✔
1838

1839

1840
def ravel(a, order="C"):
1✔
1841
    """
1842
    Return a contiguous flattened array.
1843

1844
    For full documentation refer to :obj:`numpy.ravel`.
1845

1846
    Parameters
1847
    ----------
1848
    x : {dpnp.ndarray, usm_ndarray}
1849
        Input array. The elements in `a` are read in the order specified by
1850
        order, and packed as a 1-D array.
1851
    order : {"C", "F"}, optional
1852
        The elements of `a` are read using this index order. ``"C"`` means to
1853
        index the elements in row-major, C-style order, with the last axis
1854
        index changing fastest, back to the first axis index changing slowest.
1855
        ``"F"`` means to index the elements in column-major, Fortran-style
1856
        order, with the first index changing fastest, and the last index
1857
        changing slowest. By default, ``"C"`` index order is used.
1858

1859
    Returns
1860
    -------
1861
    out : dpnp.ndarray
1862
        A contiguous 1-D array of the same subtype as `a`, with shape (a.size,).
1863

1864
    See Also
1865
    --------
1866
    :obj:`dpnp.reshape` : Change the shape of an array without changing its
1867
                          data.
1868

1869
    Examples
1870
    --------
1871
    >>> import dpnp as np
1872
    >>> x = np.array([[1, 2, 3], [4, 5, 6]])
1873
    >>> np.ravel(x)
1874
    array([1, 2, 3, 4, 5, 6])
1875

1876
    >>> x.reshape(-1)
1877
    array([1, 2, 3, 4, 5, 6])
1878

1879
    >>> np.ravel(x, order='F')
1880
    array([1, 4, 2, 5, 3, 6])
1881

1882
    """
1883

1884
    return dpnp.reshape(a, -1, order=order)
1✔
1885

1886

1887
def repeat(a, repeats, axis=None):
1✔
1888
    """
1889
    Repeat elements of an array.
1890

1891
    For full documentation refer to :obj:`numpy.repeat`.
1892

1893
    Parameters
1894
    ----------
1895
    x : {dpnp.ndarray, usm_ndarray}
1896
        Input array.
1897
    repeats : {int, tuple, list, range, dpnp.ndarray, usm_ndarray}
1898
        The number of repetitions for each element. `repeats` is broadcasted to
1899
        fit the shape of the given axis.
1900
        If `repeats` is an array, it must have an integer data type.
1901
        Otherwise, `repeats` must be a Python integer or sequence of Python
1902
        integers (i.e., a tuple, list, or range).
1903
    axis : {None, int}, optional
1904
        The axis along which to repeat values. By default, use the flattened
1905
        input array, and return a flat output array.
1906
        Default: ``None``.
1907

1908
    Returns
1909
    -------
1910
    out : dpnp.ndarray
1911
        Output array which has the same shape as `a`, except along the given
1912
        axis.
1913

1914
    See Also
1915
    --------
1916
    :obj:`dpnp.tile` : Tile an array.
1917
    :obj:`dpnp.unique` : Find the unique elements of an array.
1918

1919
    Examples
1920
    --------
1921
    >>> import dpnp as np
1922
    >>> x = np.array([3])
1923
    >>> np.repeat(x, 4)
1924
    array([3, 3, 3, 3])
1925

1926
    >>> x = np.array([[1, 2], [3, 4]])
1927
    >>> np.repeat(x, 2)
1928
    array([1, 1, 2, 2, 3, 3, 4, 4])
1929
    >>> np.repeat(x, 3, axis=1)
1930
    array([[1, 1, 1, 2, 2, 2],
1931
           [3, 3, 3, 4, 4, 4]])
1932
    >>> np.repeat(x, [1, 2], axis=0)
1933
    array([[1, 2],
1934
           [3, 4],
1935
           [3, 4]])
1936

1937
    """
1938

1939
    dpnp.check_supported_arrays_type(a)
1✔
1940
    if not isinstance(repeats, (int, tuple, list, range)):
1✔
1941
        repeats = dpnp.get_usm_ndarray(repeats)
1✔
1942

1943
    if axis is None and a.ndim > 1:
1✔
1944
        a = dpnp.ravel(a)
1✔
1945

1946
    usm_arr = dpnp.get_usm_ndarray(a)
1✔
1947
    usm_res = dpt.repeat(usm_arr, repeats, axis=axis)
1✔
1948
    return dpnp_array._create_from_usm_ndarray(usm_res)
1✔
1949

1950

1951
def require(a, dtype=None, requirements=None, *, like=None):
1✔
1952
    """
1953
    Return a :class:`dpnp.ndarray` of the provided type that satisfies
1954
    requirements.
1955

1956
    This function is useful to be sure that an array with the correct flags
1957
    is returned for passing to compiled code (perhaps through ctypes).
1958

1959
    For full documentation refer to :obj:`numpy.require`.
1960

1961
    Parameters
1962
    ----------
1963
    a : {dpnp.ndarray, usm_ndarray}
1964
       The input array to be converted to a type-and-requirement-satisfying
1965
       array.
1966
    dtype : {None, data-type}, optional
1967
       The required data-type. If ``None`` preserve the current dtype.
1968
    requirements : {None, str, sequence of str}, optional
1969
       The requirements list can be any of the following:
1970

1971
       * 'F_CONTIGUOUS' ('F') - ensure a Fortran-contiguous array
1972
       * 'C_CONTIGUOUS' ('C') - ensure a C-contiguous array
1973
       * 'WRITABLE' ('W') - ensure a writable array
1974

1975
    Returns
1976
    -------
1977
    out : dpnp.ndarray
1978
        Array with specified requirements and type if given.
1979

1980
    Limitations
1981
    -----------
1982
    Parameter `like` is supported only with default value ``None``.
1983
    Otherwise, the function raises `NotImplementedError` exception.
1984

1985
    See Also
1986
    --------
1987
    :obj:`dpnp.asarray` : Convert input to an ndarray.
1988
    :obj:`dpnp.asanyarray` : Convert to an ndarray, but pass through
1989
                        ndarray subclasses.
1990
    :obj:`dpnp.ascontiguousarray` : Convert input to a contiguous array.
1991
    :obj:`dpnp.asfortranarray` : Convert input to an ndarray with
1992
                        column-major memory order.
1993
    :obj:`dpnp.ndarray.flags` : Information about the memory layout
1994
                        of the array.
1995

1996
    Notes
1997
    -----
1998
    The returned array will be guaranteed to have the listed requirements
1999
    by making a copy if needed.
2000

2001
    Examples
2002
    --------
2003
    >>> import dpnp as np
2004
    >>> x = np.arange(6).reshape(2, 3)
2005
    >>> x.flags
2006
      C_CONTIGUOUS : True
2007
      F_CONTIGUOUS : False
2008
      WRITEABLE : True
2009

2010
    >>> y = np.require(x, dtype=np.float32, requirements=['W', 'F'])
2011
    >>> y.flags
2012
      C_CONTIGUOUS : False
2013
      F_CONTIGUOUS : True
2014
      WRITEABLE : True
2015

2016
    """
2017

2018
    dpnp.check_limitations(like=like)
1✔
2019
    dpnp.check_supported_arrays_type(a)
1✔
2020

2021
    possible_flags = {
1✔
2022
        "C": "C",
2023
        "C_CONTIGUOUS": "C",
2024
        "F": "F",
2025
        "F_CONTIGUOUS": "F",
2026
        "W": "W",
2027
        "WRITEABLE": "W",
2028
    }
2029

2030
    if not requirements:
1✔
2031
        return dpnp.asanyarray(a, dtype=dtype)
1✔
2032

2033
    try:
1✔
2034
        requirements = {possible_flags[x.upper()] for x in requirements}
1✔
2035
    except KeyError as exc:
1✔
2036
        incorrect_flag = (set(requirements) - set(possible_flags.keys())).pop()
1✔
2037
        raise ValueError(
1✔
2038
            f"Incorrect flag {incorrect_flag} in requirements"
2039
        ) from exc
2040

2041
    order = "A"
1✔
2042
    if requirements.issuperset({"C", "F"}):
1✔
2043
        raise ValueError("Cannot specify both 'C' and 'F' order")
1✔
2044
    if "F" in requirements:
1✔
2045
        order = "F"
1✔
2046
        requirements.remove("F")
1✔
2047
    elif "C" in requirements:
1✔
2048
        order = "C"
1✔
2049
        requirements.remove("C")
1✔
2050

2051
    arr = dpnp.array(a, dtype=dtype, order=order, copy=None)
1✔
2052
    if not arr.flags["W"]:
1✔
2053
        return arr.copy(order)
1✔
2054

2055
    return arr
1✔
2056

2057

2058
def reshape(a, /, newshape, order="C", copy=None):
1✔
2059
    """
2060
    Gives a new shape to an array without changing its data.
2061

2062
    For full documentation refer to :obj:`numpy.reshape`.
2063

2064
    Parameters
2065
    ----------
2066
    a : {dpnp.ndarray, usm_ndarray}
2067
        Array to be reshaped.
2068
    newshape : int or tuple of ints
2069
        The new shape should be compatible with the original shape. If
2070
        an integer, then the result will be a 1-D array of that length.
2071
        One shape dimension can be -1. In this case, the value is
2072
        inferred from the length of the array and remaining dimensions.
2073
    order : {"C", "F"}, optional
2074
        Read the elements of `a` using this index order, and place the
2075
        elements into the reshaped array using this index order. ``"C"``
2076
        means to read / write the elements using C-like index order,
2077
        with the last axis index changing fastest, back to the first
2078
        axis index changing slowest. ``"F"`` means to read / write the
2079
        elements using Fortran-like index order, with the first index
2080
        changing fastest, and the last index changing slowest. Note that
2081
        the ``"C"`` and ``"F"`` options take no account of the memory layout of
2082
        the underlying array, and only refer to the order of indexing.
2083
    copy : {None, bool}, optional
2084
        Boolean indicating whether or not to copy the input array.
2085
        If ``True``, the result array will always be a copy of input `a`.
2086
        If ``False``, the result array can never be a copy
2087
        and a ValueError exception will be raised in case the copy is necessary.
2088
        If ``None``, the result array will reuse existing memory buffer of `a`
2089
        if possible and copy otherwise.
2090
        Default: ``None``.
2091

2092
    Returns
2093
    -------
2094
    out : dpnp.ndarray
2095
        This will be a new view object if possible; otherwise, it will
2096
        be a copy.  Note there is no guarantee of the *memory layout* (C- or
2097
        Fortran- contiguous) of the returned array.
2098

2099
    Limitations
2100
    -----------
2101
    Parameter `order` is supported only with values ``"C"`` and ``"F"``.
2102

2103
    See Also
2104
    --------
2105
    :obj:`dpnp.ndarray.reshape` : Equivalent method.
2106

2107
    Examples
2108
    --------
2109
    >>> import dpnp as np
2110
    >>> a = np.array([[1, 2, 3], [4, 5, 6]])
2111
    >>> np.reshape(a, 6)
2112
    array([1, 2, 3, 4, 5, 6])
2113
    >>> np.reshape(a, 6, order='F')
2114
    array([1, 4, 2, 5, 3, 6])
2115

2116
    >>> np.reshape(a, (3, -1))       # the unspecified value is inferred to be 2
2117
    array([[1, 2],
2118
           [3, 4],
2119
           [5, 6]])
2120

2121
    """
2122

2123
    if newshape is None:
1!
2124
        newshape = a.shape
×
2125

2126
    if order is None:
1!
2127
        order = "C"
×
2128
    elif order not in "cfCF":
1✔
2129
        raise ValueError(f"order must be one of 'C' or 'F' (got {order})")
1✔
2130

2131
    usm_a = dpnp.get_usm_ndarray(a)
1✔
2132
    usm_res = dpt.reshape(usm_a, shape=newshape, order=order, copy=copy)
1✔
2133
    return dpnp_array._create_from_usm_ndarray(usm_res)
1✔
2134

2135

2136
def resize(a, new_shape):
1✔
2137
    """
2138
    Return a new array with the specified shape.
2139

2140
    If the new array is larger than the original array, then the new array is
2141
    filled with repeated copies of `a`. Note that this behavior is different
2142
    from ``a.resize(new_shape)`` which fills with zeros instead of repeated
2143
    copies of `a`.
2144

2145
    For full documentation refer to :obj:`numpy.resize`.
2146

2147
    Parameters
2148
    ----------
2149
    a : {dpnp.ndarray, usm_ndarray}
2150
        Array to be resized.
2151
    new_shape : {int, tuple or list of ints}
2152
        Shape of resized array.
2153

2154
    Returns
2155
    -------
2156
    out : dpnp.ndarray
2157
        The new array is formed from the data in the old array, repeated
2158
        if necessary to fill out the required number of elements. The
2159
        data are repeated iterating over the array in C-order.
2160

2161
    See Also
2162
    --------
2163
    :obj:`dpnp.ndarray.resize` : Resize an array in-place.
2164
    :obj:`dpnp.reshape` : Reshape an array without changing the total size.
2165
    :obj:`dpnp.pad` : Enlarge and pad an array.
2166
    :obj:`dpnp.repeat` : Repeat elements of an array.
2167

2168
    Notes
2169
    -----
2170
    When the total size of the array does not change :obj:`dpnp.reshape` should
2171
    be used. In most other cases either indexing (to reduce the size) or
2172
    padding (to increase the size) may be a more appropriate solution.
2173

2174
    Warning: This functionality does **not** consider axes separately,
2175
    i.e. it does not apply interpolation/extrapolation.
2176
    It fills the return array with the required number of elements, iterating
2177
    over `a` in C-order, disregarding axes (and cycling back from the start if
2178
    the new shape is larger). This functionality is therefore not suitable to
2179
    resize images, or data where each axis represents a separate and distinct
2180
    entity.
2181

2182
    Examples
2183
    --------
2184
    >>> import dpnp as np
2185
    >>> a = np.array([[0, 1], [2, 3]])
2186
    >>> np.resize(a, (2, 3))
2187
    array([[0, 1, 2],
2188
           [3, 0, 1]])
2189
    >>> np.resize(a, (1, 4))
2190
    array([[0, 1, 2, 3]])
2191
    >>> np.resize(a, (2, 4))
2192
    array([[0, 1, 2, 3],
2193
           [0, 1, 2, 3]])
2194

2195
    """
2196

2197
    dpnp.check_supported_arrays_type(a)
1✔
2198
    if a.ndim == 0:
1✔
2199
        return dpnp.full_like(a, a, shape=new_shape)
1✔
2200

2201
    if isinstance(new_shape, (int, numpy.integer)):
1✔
2202
        new_shape = (new_shape,)
1✔
2203

2204
    new_size = 1
1✔
2205
    for dim_length in new_shape:
1✔
2206
        if dim_length < 0:
1✔
2207
            raise ValueError("all elements of `new_shape` must be non-negative")
1✔
2208
        new_size *= dim_length
1✔
2209

2210
    a_size = a.size
1✔
2211
    if a_size == 0 or new_size == 0:
1✔
2212
        # First case must zero fill. The second would have repeats == 0.
2213
        return dpnp.zeros_like(a, shape=new_shape)
1✔
2214

2215
    repeats = -(-new_size // a_size)  # ceil division
1✔
2216
    a = dpnp.concatenate((dpnp.ravel(a),) * repeats)[:new_size]
1✔
2217

2218
    return a.reshape(new_shape)
1✔
2219

2220

2221
def result_type(*arrays_and_dtypes):
1✔
2222
    """
2223
    result_type(*arrays_and_dtypes)
2224

2225
    Returns the type that results from applying the NumPy
2226
    type promotion rules to the arguments.
2227

2228
    For full documentation refer to :obj:`numpy.result_type`.
2229

2230
    Parameters
2231
    ----------
2232
    arrays_and_dtypes : list of {dpnp.ndarray, usm_ndarray, dtype}
2233
        An arbitrary length sequence of arrays or dtypes.
2234

2235
    Returns
2236
    -------
2237
    out : dtype
2238
        The result type.
2239

2240
    Examples
2241
    --------
2242
    >>> import dpnp as np
2243
    >>> a = np.arange(3, dtype=np.int64)
2244
    >>> b = np.arange(7, dtype=np.int32)
2245
    >>> np.result_type(a, b)
2246
    dtype('int64')
2247

2248
    >>> np.result_type(np.int64, np.complex128)
2249
    dtype('complex128')
2250

2251
    >>> np.result_type(np.ones(10, dtype=np.float32), np.float64)
2252
    dtype('float64')
2253

2254
    """
2255

2256
    usm_arrays_and_dtypes = [
1✔
2257
        (
2258
            dpnp.get_usm_ndarray(X)
2259
            if isinstance(X, (dpnp_array, dpt.usm_ndarray))
2260
            else X
2261
        )
2262
        for X in arrays_and_dtypes
2263
    ]
2264
    return dpt.result_type(*usm_arrays_and_dtypes)
1✔
2265

2266

2267
def roll(x, shift, axis=None):
1✔
2268
    """
2269
    Roll the elements of an array by a number of positions along a given axis.
2270

2271
    Array elements that roll beyond the last position are re-introduced
2272
    at the first position. Array elements that roll beyond the first position
2273
    are re-introduced at the last position.
2274

2275
    For full documentation refer to :obj:`numpy.roll`.
2276

2277
    Parameters
2278
    ----------
2279
    a : {dpnp.ndarray, usm_ndarray}
2280
        Input array.
2281
    shift : {int, tuple of ints}
2282
        The number of places by which elements are shifted. If a tuple, then
2283
        `axis` must be a tuple of the same size, and each of the given axes
2284
        is shifted by the corresponding number. If an integer while `axis` is
2285
        a tuple of integers, then the same value is used for all given axes.
2286
    axis : {None, int, tuple of ints}, optional
2287
        Axis or axes along which elements are shifted. By default, the
2288
        array is flattened before shifting, after which the original
2289
        shape is restored.
2290

2291
    Returns
2292
    -------
2293
    out : dpnp.ndarray
2294
        An array with the same data type as `x`
2295
        and whose elements, relative to `x`, are shifted.
2296

2297
    See Also
2298
    --------
2299
    :obj:`dpnp.moveaxis` : Move array axes to new positions.
2300
    :obj:`dpnp.rollaxis` : Roll the specified axis backwards
2301
                       until it lies in a given position.
2302

2303
    Examples
2304
    --------
2305
    >>> import dpnp as np
2306
    >>> x1 = np.arange(10)
2307
    >>> np.roll(x1, 2)
2308
    array([8, 9, 0, 1, 2, 3, 4, 5, 6, 7])
2309

2310
    >>> np.roll(x1, -2)
2311
    array([2, 3, 4, 5, 6, 7, 8, 9, 0, 1])
2312

2313
    >>> x2 = np.reshape(x1, (2, 5))
2314
    >>> np.roll(x2, 1, axis=0)
2315
    array([[5, 6, 7, 8, 9],
2316
           [0, 1, 2, 3, 4]])
2317

2318
    >>> np.roll(x2, (2, 1), axis=(1, 0))
2319
    array([[8, 9, 5, 6, 7],
2320
           [3, 4, 0, 1, 2]])
2321

2322
    """
2323
    if axis is None:
1✔
2324
        return roll(x.reshape(-1), shift, 0).reshape(x.shape)
1✔
2325

2326
    usm_x = dpnp.get_usm_ndarray(x)
1✔
2327
    usm_res = dpt.roll(usm_x, shift=shift, axis=axis)
1✔
2328
    return dpnp_array._create_from_usm_ndarray(usm_res)
1✔
2329

2330

2331
def rollaxis(x, axis, start=0):
1✔
2332
    """
2333
    Roll the specified axis backwards, until it lies in a given position.
2334

2335
    For full documentation refer to :obj:`numpy.rollaxis`.
2336

2337
    Parameters
2338
    ----------
2339
    a : {dpnp.ndarray, usm_ndarray}
2340
        Input array.
2341
    axis : int
2342
        The axis to be rolled. The positions of the other axes do not
2343
        change relative to one another.
2344
    start : int, optional
2345
        When ``start <= axis``, the axis is rolled back until it lies in
2346
        this position. When ``start > axis``, the axis is rolled until it
2347
        lies before this position. The default, ``0``, results in a "complete"
2348
        roll.
2349

2350
    Returns
2351
    -------
2352
    out : dpnp.ndarray
2353
        An array with the same data type as `x` where the specified axis
2354
        has been moved to the requested position.
2355

2356
    See Also
2357
    --------
2358
    :obj:`dpnp.moveaxis` : Move array axes to new positions.
2359
    :obj:`dpnp.roll` : Roll the elements of an array
2360
                       by a number of positions along a given axis.
2361

2362
    Examples
2363
    --------
2364
    >>> import dpnp as np
2365
    >>> a = np.ones((3,4,5,6))
2366
    >>> np.rollaxis(a, 3, 1).shape
2367
    (3, 6, 4, 5)
2368
    >>> np.rollaxis(a, 2).shape
2369
    (5, 3, 4, 6)
2370
    >>> np.rollaxis(a, 1, 4).shape
2371
    (3, 5, 6, 4)
2372

2373
    """
2374

2375
    n = x.ndim
1✔
2376
    axis = normalize_axis_index(axis, n)
1✔
2377
    if start < 0:
1✔
2378
        start += n
1✔
2379
    msg = "'%s' arg requires %d <= %s < %d, but %d was passed in"
1✔
2380
    if not 0 <= start < n + 1:
1✔
2381
        raise ValueError(msg % ("start", -n, "start", n + 1, start))
1✔
2382
    if axis < start:
1✔
2383
        start -= 1
1✔
2384
    if axis == start:
1✔
2385
        return x
1✔
2386
    usm_array = dpnp.get_usm_ndarray(x)
1✔
2387
    return dpnp.moveaxis(usm_array, source=axis, destination=start)
1✔
2388

2389

2390
def rot90(m, k=1, axes=(0, 1)):
1✔
2391
    """
2392
    Rotate an array by 90 degrees in the plane specified by axes.
2393

2394
    Rotation direction is from the first towards the second axis.
2395
    This means for a 2D array with the default `k` and `axes`, the
2396
    rotation will be counterclockwise.
2397

2398
    For full documentation refer to :obj:`numpy.rot90`.
2399

2400
    Parameters
2401
    ----------
2402
    m : {dpnp.ndarray, usm_ndarray}
2403
        Array of two or more dimensions.
2404
    k : integer, optional
2405
        Number of times the array is rotated by 90 degrees.
2406
        Default: ``1``.
2407
    axes : (2,) array_like of ints, optional
2408
        The array is rotated in the plane defined by the axes.
2409
        Axes must be different.
2410
        Default: ``(0, 1)``.
2411

2412
    Returns
2413
    -------
2414
    out : dpnp.ndarray
2415
        A rotated view of `m`.
2416

2417
    See Also
2418
    --------
2419
    :obj:`dpnp.flip` : Reverse the order of elements in an array along
2420
                    the given axis.
2421
    :obj:`dpnp.fliplr` : Flip an array horizontally.
2422
    :obj:`dpnp.flipud` : Flip an array vertically.
2423

2424
    Notes
2425
    -----
2426
    ``rot90(m, k=1, axes=(1,0))`` is the reverse of
2427
    ``rot90(m, k=1, axes=(0,1))``.
2428

2429
    ``rot90(m, k=1, axes=(1,0))`` is equivalent to
2430
    ``rot90(m, k=-1, axes=(0,1))``.
2431

2432
    Examples
2433
    --------
2434
    >>> import dpnp as np
2435
    >>> m = np.array([[1, 2], [3, 4]])
2436
    >>> m
2437
    array([[1, 2],
2438
           [3, 4]])
2439
    >>> np.rot90(m)
2440
    array([[2, 4],
2441
           [1, 3]])
2442
    >>> np.rot90(m, 2)
2443
    array([[4, 3],
2444
           [2, 1]])
2445
    >>> m = np.arange(8).reshape((2, 2, 2))
2446
    >>> np.rot90(m, 1, (1, 2))
2447
    array([[[1, 3],
2448
            [0, 2]],
2449
           [[5, 7],
2450
            [4, 6]]])
2451

2452
    """
2453

2454
    dpnp.check_supported_arrays_type(m)
1✔
2455
    k = operator.index(k)
1✔
2456

2457
    m_ndim = m.ndim
1✔
2458
    if m_ndim < 2:
1✔
2459
        raise ValueError("Input must be at least 2-d.")
1✔
2460

2461
    if len(axes) != 2:
1✔
2462
        raise ValueError("len(axes) must be 2.")
1✔
2463

2464
    if axes[0] == axes[1] or abs(axes[0] - axes[1]) == m_ndim:
1✔
2465
        raise ValueError("Axes must be different.")
1✔
2466

2467
    if not (-m_ndim <= axes[0] < m_ndim and -m_ndim <= axes[1] < m_ndim):
1✔
2468
        raise ValueError(
1✔
2469
            f"Axes={axes} out of range for array of ndim={m_ndim}."
2470
        )
2471

2472
    k %= 4
1✔
2473
    if k == 0:
1✔
2474
        return m[:]
1✔
2475
    if k == 2:
1✔
2476
        return dpnp.flip(dpnp.flip(m, axes[0]), axes[1])
1✔
2477

2478
    axes_list = list(range(0, m_ndim))
1✔
2479
    (axes_list[axes[0]], axes_list[axes[1]]) = (
1✔
2480
        axes_list[axes[1]],
2481
        axes_list[axes[0]],
2482
    )
2483

2484
    if k == 1:
1✔
2485
        return dpnp.transpose(dpnp.flip(m, axes[1]), axes_list)
1✔
2486

2487
    # k == 3
2488
    return dpnp.flip(dpnp.transpose(m, axes_list), axes[1])
1✔
2489

2490

2491
def shape(a):
1✔
2492
    """
2493
    Return the shape of an array.
2494

2495
    For full documentation refer to :obj:`numpy.shape`.
2496

2497
    Parameters
2498
    ----------
2499
    a : array_like
2500
        Input array.
2501

2502
    Returns
2503
    -------
2504
    shape : tuple of integers
2505
        The elements of the shape tuple give the lengths of the
2506
        corresponding array dimensions.
2507

2508
    See Also
2509
    --------
2510
    len : ``len(a)`` is equivalent to ``np.shape(a)[0]`` for N-D arrays with
2511
          ``N>=1``.
2512
    :obj:`dpnp.ndarray.shape` : Equivalent array method.
2513

2514
    Examples
2515
    --------
2516
    >>> import dpnp as np
2517
    >>> np.shape(np.eye(3))
2518
    (3, 3)
2519
    >>> np.shape([[1, 3]])
2520
    (1, 2)
2521
    >>> np.shape([0])
2522
    (1,)
2523
    >>> np.shape(0)
2524
    ()
2525

2526
    """
2527

2528
    if dpnp.is_supported_array_type(a):
1✔
2529
        return a.shape
1✔
2530
    return numpy.shape(a)
1✔
2531

2532

2533
def size(a, axis=None):
1✔
2534
    """
2535
    Return the number of elements along a given axis.
2536

2537
    For full documentation refer to :obj:`numpy.size`.
2538

2539
    Parameters
2540
    ----------
2541
    a : array_like
2542
        Input data.
2543
    axis : {None, int}, optional
2544
        Axis along which the elements are counted.
2545
        By default, give the total number of elements.
2546
        Default: ``None``.
2547

2548
    Returns
2549
    -------
2550
    element_count : int
2551
        Number of elements along the specified axis.
2552

2553
    See Also
2554
    --------
2555
    :obj:`dpnp.ndarray.size` : number of elements in array.
2556
    :obj:`dpnp.shape` : Return the shape of an array.
2557
    :obj:`dpnp.ndarray.shape` : Return the shape of an array.
2558

2559
    Examples
2560
    --------
2561
    >>> import dpnp as np
2562
    >>> a = [[1, 2, 3], [4, 5, 6]]
2563
    >>> np.size(a)
2564
    6
2565
    >>> np.size(a, 1)
2566
    3
2567
    >>> np.size(a, 0)
2568
    2
2569

2570
    >>> a = np.asarray(a)
2571
    >>> np.size(a)
2572
    6
2573
    >>> np.size(a, 1)
2574
    3
2575

2576
    """
2577

2578
    if dpnp.is_supported_array_type(a):
1✔
2579
        if axis is None:
1✔
2580
            return a.size
1✔
2581
        return a.shape[axis]
1✔
2582

2583
    return numpy.size(a, axis)
1✔
2584

2585

2586
def split(ary, indices_or_sections, axis=0):
1✔
2587
    """
2588
    Split an array into multiple sub-arrays as views into `ary`.
2589

2590
    For full documentation refer to :obj:`numpy.split`.
2591

2592
    Parameters
2593
    ----------
2594
    ary : {dpnp.ndarray, usm_ndarray}
2595
        Array to be divided into sub-arrays.
2596
    indices_or_sections : {int, sequence of ints}
2597
        If `indices_or_sections` is an integer, N, the array will be divided
2598
        into N equal arrays along `axis`. If such a split is not possible,
2599
        an error is raised.
2600

2601
        If `indices_or_sections` is a sequence of sorted integers, the entries
2602
        indicate where along `axis` the array is split. For example,
2603
        ``[2, 3]`` would, for ``axis=0``, result in
2604

2605
        - ary[:2]
2606
        - ary[2:3]
2607
        - ary[3:]
2608

2609
        If an index exceeds the dimension of the array along `axis`,
2610
        an empty sub-array is returned correspondingly.
2611
    axis : int, optional
2612
        The axis along which to split.
2613
        Default: ``0``.
2614

2615
    Returns
2616
    -------
2617
    sub-arrays : list of dpnp.ndarray
2618
        A list of sub arrays. Each array is a view of the corresponding input
2619
        array.
2620

2621
    Raises
2622
    ------
2623
    ValueError
2624
        If `indices_or_sections` is given as an integer, but
2625
        a split does not result in equal division.
2626

2627
    See Also
2628
    --------
2629
    :obj:`dpnp.array_split` : Split an array into multiple sub-arrays of equal
2630
                        or near-equal size. Does not raise an exception if an
2631
                        equal division cannot be made.
2632
    :obj:`dpnp.hsplit` : Split array into multiple sub-arrays horizontally
2633
                    (column-wise).
2634
    :obj:`dpnp.vsplit` : Split array into multiple sub-arrays vertically
2635
                    (row wise).
2636
    :obj:`dpnp.dsplit` : Split array into multiple sub-arrays along the 3rd
2637
                    axis (depth).
2638
    :obj:`dpnp.concatenate` : Join a sequence of arrays along an existing axis.
2639
    :obj:`dpnp.stack` : Join a sequence of arrays along a new axis.
2640
    :obj:`dpnp.hstack` : Stack arrays in sequence horizontally (column wise).
2641
    :obj:`dpnp.vstack` : Stack arrays in sequence vertically (row wise).
2642
    :obj:`dpnp.dstack` : Stack arrays in sequence depth wise
2643
                    (along third dimension).
2644

2645
    Examples
2646
    --------
2647
    >>> import dpnp as np
2648
    >>> x = np.arange(9.0)
2649
    >>> np.split(x, 3)
2650
    [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7., 8.])]
2651

2652
    >>> x = np.arange(8.0)
2653
    >>> np.split(x, [3, 5, 6, 10])
2654
    [array([0., 1., 2.]), array([3., 4.]), array([5.]), array([6., 7.]), \
2655
    array([])]
2656

2657
    """
2658

2659
    dpnp.check_supported_arrays_type(ary)
1✔
2660
    if ary.ndim <= axis:
1✔
2661
        raise IndexError("Axis exceeds ndim")
1✔
2662

2663
    try:
1✔
2664
        len(indices_or_sections)
1✔
2665
    except TypeError:
1✔
2666
        if ary.shape[axis] % indices_or_sections != 0:
1✔
2667
            raise ValueError(
1✔
2668
                "indices_or_sections must divide the size along the axes.\n"
2669
                "If you want to split the array into non-equally-sized "
2670
                "arrays, use array_split instead."
2671
            ) from None
2672

2673
    return array_split(ary, indices_or_sections, axis)
1✔
2674

2675

2676
def squeeze(a, /, axis=None):
1✔
2677
    """
2678
    Removes singleton dimensions (axes) from array `a`.
2679

2680
    For full documentation refer to :obj:`numpy.squeeze`.
2681

2682
    Parameters
2683
    ----------
2684
    a : {dpnp.ndarray, usm_ndarray}
2685
        Input data.
2686
    axis : None or int or tuple of ints, optional
2687
        Selects a subset of the entries of length one in the shape.
2688
        If an axis is selected with shape entry greater than one,
2689
        an error is raised.
2690

2691
    Returns
2692
    -------
2693
    out : dpnp.ndarray
2694
        Output array is a view, if possible, and a copy otherwise, but with all
2695
        or a subset of the dimensions of length 1 removed. Output has the same
2696
        data type as the input, is allocated on the same device as the input
2697
        and has the same USM allocation type as the input array `a`.
2698

2699
    Examples
2700
    --------
2701
    >>> import dpnp as np
2702
    >>> x = np.array([[[0], [1], [2]]])
2703
    >>> x.shape
2704
    (1, 3, 1)
2705
    >>> np.squeeze(x).shape
2706
    (3,)
2707
    >>> np.squeeze(x, axis=0).shape
2708
    (3, 1)
2709
    >>> np.squeeze(x, axis=1).shape
2710
    Traceback (most recent call last):
2711
    ...
2712
    ValueError: Cannot select an axis to squeeze out which has size not equal
2713
    to one.
2714
    >>> np.squeeze(x, axis=2).shape
2715
    (1, 3)
2716

2717
    """
2718

2719
    usm_a = dpnp.get_usm_ndarray(a)
1✔
2720
    usm_res = dpt.squeeze(usm_a, axis=axis)
1✔
2721
    return dpnp_array._create_from_usm_ndarray(usm_res)
1✔
2722

2723

2724
def stack(arrays, /, *, axis=0, out=None, dtype=None, casting="same_kind"):
1✔
2725
    """
2726
    Join a sequence of arrays along a new axis.
2727

2728
    For full documentation refer to :obj:`numpy.stack`.
2729

2730
    Parameters
2731
    ----------
2732
    arrays : {dpnp.ndarray, usm_ndarray}
2733
        Each array must have the same shape.
2734
    axis : int, optional
2735
        The axis in the result array along which the input arrays are stacked.
2736
    out : dpnp.ndarray, optional
2737
        If provided, the destination to place the result. The shape must be
2738
        correct, matching that of what stack would have returned if no out
2739
        argument were specified.
2740
    dtype : str or dtype
2741
        If provided, the destination array will have this dtype. Cannot be
2742
        provided together with `out`.
2743
    casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
2744
        Controls what kind of data casting may occur. Defaults to 'same_kind'.
2745

2746
    Returns
2747
    -------
2748
    out : dpnp.ndarray
2749
        The stacked array which has one more dimension than the input arrays.
2750

2751
    See Also
2752
    --------
2753
    :obj:`dpnp.concatenate` : Join a sequence of arrays along an existing axis.
2754
    :obj:`dpnp.hstack` : Stack arrays in sequence horizontally (column wise).
2755
    :obj:`dpnp.vstack` : Stack arrays in sequence vertically (row wise).
2756
    :obj:`dpnp.dstack` : Stack arrays in sequence depth wise
2757
                         (along third dimension).
2758
    :obj:`dpnp.column_stack` : Stack 1-D arrays as columns into a 2-D array.
2759
    :obj:`dpnp.block` : Assemble an ndarray from nested lists of blocks.
2760
    :obj:`dpnp.split` : Split array into a list of multiple sub-arrays of equal
2761
                        size.
2762

2763
    Examples
2764
    --------
2765
    >>> import dpnp as np
2766
    >>> arrays = [np.random.randn(3, 4) for _ in range(10)]
2767
    >>> np.stack(arrays, axis=0).shape
2768
    (10, 3, 4)
2769

2770
    >>> np.stack(arrays, axis=1).shape
2771
    (3, 10, 4)
2772

2773
    >>> np.stack(arrays, axis=2).shape
2774
    (3, 4, 10)
2775

2776
    >>> a = np.array([1, 2, 3])
2777
    >>> b = np.array([4, 5, 6])
2778
    >>> np.stack((a, b))
2779
    array([[1, 2, 3],
2780
           [4, 5, 6]])
2781

2782
    >>> np.stack((a, b), axis=-1)
2783
    array([[1, 4],
2784
           [2, 5],
2785
           [3, 6]])
2786

2787
    """
2788

2789
    _check_stack_arrays(arrays)
1✔
2790

2791
    if dtype is not None and out is not None:
1✔
2792
        raise TypeError(
1✔
2793
            "stack() only takes `out` or `dtype` as an argument, "
2794
            "but both were provided."
2795
        )
2796

2797
    usm_arrays = [dpnp.get_usm_ndarray(x) for x in arrays]
1✔
2798
    usm_res = dpt.stack(usm_arrays, axis=axis)
1✔
2799

2800
    res = dpnp_array._create_from_usm_ndarray(usm_res)
1✔
2801
    if dtype is not None:
1✔
2802
        res = res.astype(dtype, casting=casting, copy=False)
1✔
2803
    elif out is not None:
1✔
2804
        dpnp.copyto(out, res, casting=casting)
1✔
2805
        return out
1✔
2806
    return res
1✔
2807

2808

2809
def swapaxes(a, axis1, axis2):
1✔
2810
    """
2811
    Interchange two axes of an array.
2812

2813
    For full documentation refer to :obj:`numpy.swapaxes`.
2814

2815
    Parameters
2816
    ----------
2817
    a : {dpnp.ndarray, usm_ndarray}
2818
        Input array.
2819
    axis1 : int
2820
        First axis.
2821
    axis2 : int
2822
        Second axis.
2823

2824
    Returns
2825
    -------
2826
    out : dpnp.ndarray
2827
        An array with with swapped axes.
2828
        A view is returned whenever possible.
2829

2830
    Notes
2831
    -----
2832
    If `a` has rank (i.e., number of dimensions) `N`,
2833
    a valid `axis` must be in the half-open interval `[-N, N)`.
2834

2835
    Examples
2836
    --------
2837
    >>> import dpnp as np
2838
    >>> x = np.array([[1, 2, 3]])
2839
    >>> np.swapaxes(x, 0, 1)
2840
    array([[1],
2841
           [2],
2842
           [3]])
2843

2844
    >>> x = np.array([[[0,1],[2,3]],[[4,5],[6,7]]])
2845
    >>> x
2846
    array([[[0, 1],
2847
            [2, 3]],
2848
           [[4, 5],
2849
            [6, 7]]])
2850
    >>> np.swapaxes(x,0,2)
2851
    array([[[0, 4],
2852
            [2, 6]],
2853
           [[1, 5],
2854
            [3, 7]]])
2855

2856
    """
2857

2858
    usm_a = dpnp.get_usm_ndarray(a)
1✔
2859
    usm_res = dpt.swapaxes(usm_a, axis1=axis1, axis2=axis2)
1✔
2860
    return dpnp_array._create_from_usm_ndarray(usm_res)
1✔
2861

2862

2863
# pylint: disable=invalid-name
2864
def tile(A, reps):
1✔
2865
    """
2866
    Construct an array by repeating `A` the number of times given by reps.
2867

2868
    If `reps` has length ``d``, the result will have dimension of
2869
    ``max(d, A.ndim)``.
2870

2871
    If ``A.ndim < d``, `A` is promoted to be d-dimensional by prepending new
2872
    axes. So a shape (3,) array is promoted to (1, 3) for 2-D replication,
2873
    or shape (1, 1, 3) for 3-D replication. If this is not the desired
2874
    behavior, promote `A` to d-dimensions manually before calling this
2875
    function.
2876

2877
    If ``A.ndim > d``, `reps` is promoted to `A`.ndim by prepending 1's to it.
2878
    Thus for an `A` of shape (2, 3, 4, 5), a `reps` of (2, 2) is treated as
2879
    (1, 1, 2, 2).
2880

2881
    Note : Although tile may be used for broadcasting, it is strongly
2882
    recommended to use dpnp's broadcasting operations and functions.
2883

2884
    For full documentation refer to :obj:`numpy.tile`.
2885

2886
    Parameters
2887
    ----------
2888
    A : {dpnp.ndarray, usm_ndarray}
2889
        The input array.
2890
    reps : int or tuple of ints
2891
        The number of repetitions of `A` along each axis.
2892

2893
    Returns
2894
    -------
2895
    out : dpnp.ndarray
2896
        The tiled output array.
2897

2898
    See Also
2899
    --------
2900
    :obj:`dpnp.repeat` : Repeat elements of an array.
2901
    :obj:`dpnp.broadcast_to` : Broadcast an array to a new shape
2902

2903
    Examples
2904
    --------
2905
    >>> import dpnp as np
2906
    >>> a = np.array([0, 1, 2])
2907
    >>> np.tile(a, 2)
2908
    array([0, 1, 2, 0, 1, 2])
2909

2910
    >>> np.tile(a, (2, 2))
2911
    array([[0, 1, 2, 0, 1, 2],
2912
           [0, 1, 2, 0, 1, 2]])
2913

2914
    >>> np.tile(a, (2, 1, 2))
2915
    array([[[0, 1, 2, 0, 1, 2]],
2916
           [[0, 1, 2, 0, 1, 2]]])
2917

2918
    >>> b = np.array([[1, 2], [3, 4]])
2919
    >>> np.tile(b, 2)
2920
    array([[1, 2, 1, 2],
2921
           [3, 4, 3, 4]])
2922

2923
    >>> np.tile(b, (2, 1))
2924
    array([[1, 2],
2925
           [3, 4],
2926
           [1, 2],
2927
           [3, 4]])
2928

2929
    >>> c = np.array([1, 2, 3, 4])
2930
    >>> np.tile(c, (4, 1))
2931
    array([[1, 2, 3, 4],
2932
           [1, 2, 3, 4],
2933
           [1, 2, 3, 4],
2934
           [1, 2, 3, 4]])
2935

2936
    """
2937

2938
    usm_a = dpnp.get_usm_ndarray(A)
1✔
2939
    usm_res = dpt.tile(usm_a, reps)
1✔
2940
    return dpnp_array._create_from_usm_ndarray(usm_res)
1✔
2941

2942

2943
def transpose(a, axes=None):
1✔
2944
    """
2945
    Returns an array with axes transposed.
2946

2947
    Note that :obj:`dpnp.permute_dims` is an alias of :obj:`dpnp.transpose`.
2948

2949
    For full documentation refer to :obj:`numpy.transpose`.
2950

2951
    Parameters
2952
    ----------
2953
    a : {dpnp.ndarray, usm_ndarray}
2954
        Input array.
2955
    axes : None, tuple or list of ints, optional
2956
        If specified, it must be a tuple or list which contains a permutation
2957
        of [0, 1, ..., N-1] where N is the number of axes of `a`.
2958
        The `i`'th axis of the returned array will correspond to the axis
2959
        numbered ``axes[i]`` of the input. If not specified or ``None``,
2960
        defaults to ``range(a.ndim)[::-1]``, which reverses the order of
2961
        the axes.
2962

2963
    Returns
2964
    -------
2965
    out : dpnp.ndarray
2966
        `a` with its axes permuted. A view is returned whenever possible.
2967

2968
    See Also
2969
    --------
2970
    :obj:`dpnp.ndarray.transpose` : Equivalent method.
2971
    :obj:`dpnp.moveaxis` : Move array axes to new positions.
2972
    :obj:`dpnp.argsort` : Returns the indices that would sort an array.
2973

2974
    Examples
2975
    --------
2976
    >>> import dpnp as np
2977
    >>> a = np.array([[1, 2], [3, 4]])
2978
    >>> a
2979
    array([[1, 2],
2980
           [3, 4]])
2981
    >>> np.transpose(a)
2982
    array([[1, 3],
2983
           [2, 4]])
2984

2985
    >>> a = np.array([1, 2, 3, 4])
2986
    >>> a
2987
    array([1, 2, 3, 4])
2988
    >>> np.transpose(a)
2989
    array([1, 2, 3, 4])
2990

2991
    >>> a = np.ones((1, 2, 3))
2992
    >>> np.transpose(a, (1, 0, 2)).shape
2993
    (2, 1, 3)
2994

2995
    >>> a = np.ones((2, 3, 4, 5))
2996
    >>> np.transpose(a).shape
2997
    (5, 4, 3, 2)
2998

2999
    """
3000

3001
    if isinstance(a, dpnp_array):
1✔
3002
        array = a
1✔
3003
    elif isinstance(a, dpt.usm_ndarray):
1!
3004
        array = dpnp_array._create_from_usm_ndarray(a)
1✔
3005
    else:
3006
        raise TypeError(
×
3007
            f"An array must be any of supported type, but got {type(a)}"
3008
        )
3009

3010
    if axes is None:
1✔
3011
        return array.transpose()
1✔
3012
    return array.transpose(*axes)
1✔
3013

3014

3015
permute_dims = transpose  # permute_dims is an alias for transpose
1✔
3016

3017

3018
def trim_zeros(filt, trim="fb"):
1✔
3019
    """
3020
    Trim the leading and/or trailing zeros from a 1-D array.
3021

3022
    For full documentation refer to :obj:`numpy.trim_zeros`.
3023

3024
    Parameters
3025
    ----------
3026
    filt : {dpnp.ndarray, usm_ndarray}
3027
        Input 1-D array.
3028
    trim : str, optional
3029
        A string with 'f' representing trim from front and 'b' to trim from
3030
        back. By defaults, trim zeros from both front and back of the array.
3031
        Default: ``"fb"``.
3032

3033
    Returns
3034
    -------
3035
    out : dpnp.ndarray
3036
        The result of trimming the input.
3037

3038
    Examples
3039
    --------
3040
    >>> import dpnp as np
3041
    >>> a = np.array((0, 0, 0, 1, 2, 3, 0, 2, 1, 0))
3042
    >>> np.trim_zeros(a)
3043
    array([1, 2, 3, 0, 2, 1])
3044

3045
    >>> np.trim_zeros(a, 'b')
3046
    array([0, 0, 0, 1, 2, 3, 0, 2, 1])
3047

3048
    """
3049

3050
    dpnp.check_supported_arrays_type(filt)
1✔
3051
    if filt.ndim == 0:
1✔
3052
        raise TypeError("0-d array cannot be trimmed")
1✔
3053
    if filt.ndim > 1:
1✔
3054
        raise ValueError("Multi-dimensional trim is not supported")
1✔
3055

3056
    if not isinstance(trim, str):
1✔
3057
        raise TypeError("only string trim is supported")
1✔
3058

3059
    trim = trim.upper()
1✔
3060
    if not any(x in trim for x in "FB"):
1✔
3061
        return filt  # no trim rule is specified
1✔
3062

3063
    if filt.size == 0:
1✔
3064
        return filt  # no trailing zeros in empty array
1✔
3065

3066
    a = dpnp.nonzero(filt)[0]
1✔
3067
    a_size = a.size
1✔
3068
    if a_size == 0:
1✔
3069
        # 'filt' is array of zeros
3070
        return dpnp.empty_like(filt, shape=(0,))
1✔
3071

3072
    first = 0
1✔
3073
    if "F" in trim:
1✔
3074
        first = a[0]
1✔
3075

3076
    last = filt.size
1✔
3077
    if "B" in trim:
1✔
3078
        last = a[-1] + 1
1✔
3079

3080
    return filt[first:last]
1✔
3081

3082

3083
def unique(
1✔
3084
    ar,
3085
    return_index=False,
3086
    return_inverse=False,
3087
    return_counts=False,
3088
    axis=None,
3089
    *,
3090
    equal_nan=True,
3091
):
3092
    """
3093
    Find the unique elements of an array.
3094

3095
    Returns the sorted unique elements of an array. There are three optional
3096
    outputs in addition to the unique elements:
3097

3098
    * the indices of the input array that give the unique values
3099
    * the indices of the unique array that reconstruct the input array
3100
    * the number of times each unique value comes up in the input array
3101

3102
    For full documentation refer to :obj:`numpy.unique`.
3103

3104
    Parameters
3105
    ----------
3106
    ar : {dpnp.ndarray, usm_ndarray}
3107
        Input array. Unless `axis` is specified, this will be flattened if it
3108
        is not already 1-D.
3109
    return_index : bool, optional
3110
        If ``True``, also return the indices of `ar` (along the specified axis,
3111
        if provided, or in the flattened array) that result in the unique array.
3112
        Default: ``False``.
3113
    return_inverse : bool, optional
3114
        If ``True``, also return the indices of the unique array (for the
3115
        specified axis, if provided) that can be used to reconstruct `ar`.
3116
        Default: ``False``.
3117
    return_counts : bool, optional
3118
        If ``True``, also return the number of times each unique item appears
3119
        in `ar`.
3120
        Default: ``False``.
3121
    axis : {int, None}, optional
3122
        The axis to operate on. If ``None``, `ar` will be flattened. If an
3123
        integer, the subarrays indexed by the given axis will be flattened and
3124
        treated as the elements of a 1-D array with the dimension of the given
3125
        axis, see the notes for more details.
3126
        Default: ``None``.
3127
    equal_nan : bool, optional
3128
        If ``True``, collapses multiple NaN values in the return array into one.
3129
        Default: ``True``.
3130

3131
    Returns
3132
    -------
3133
    unique : dpnp.ndarray
3134
        The sorted unique values.
3135
    unique_indices : dpnp.ndarray, optional
3136
        The indices of the first occurrences of the unique values in the
3137
        original array. Only provided if `return_index` is ``True``.
3138
    unique_inverse : dpnp.ndarray, optional
3139
        The indices to reconstruct the original array from the unique array.
3140
        Only provided if `return_inverse` is ``True``.
3141
    unique_counts : dpnp.ndarray, optional
3142
        The number of times each of the unique values comes up in the original
3143
        array. Only provided if `return_counts` is ``True``.
3144

3145
    See Also
3146
    --------
3147
    :obj:`dpnp.repeat` : Repeat elements of an array.
3148

3149
    Notes
3150
    -----
3151
    When an axis is specified the subarrays indexed by the axis are sorted.
3152
    This is done by making the specified axis the first dimension of the array
3153
    (move the axis to the first dimension to keep the order of the other axes)
3154
    and then flattening the subarrays in C order.
3155
    For complex arrays all NaN values are considered equivalent (no matter
3156
    whether the NaN is in the real or imaginary part). As the representative for
3157
    the returned array the smallest one in the lexicographical order is chosen.
3158
    For multi-dimensional inputs, `unique_inverse` is reshaped such that the
3159
    input can be reconstructed using
3160
    ``dpnp.take(unique, unique_inverse, axis=axis)``.
3161

3162
    Examples
3163
    --------
3164
    >>> import dpnp as np
3165
    >>> a = np.array([1, 1, 2, 2, 3, 3])
3166
    >>> np.unique(a)
3167
    array([1, 2, 3])
3168
    >>> a = np.array([[1, 1], [2, 3]])
3169
    >>> np.unique(a)
3170
    array([1, 2, 3])
3171

3172
    Return the unique rows of a 2D array
3173

3174
    >>> a = np.array([[1, 0, 0], [1, 0, 0], [2, 3, 4]])
3175
    >>> np.unique(a, axis=0)
3176
    array([[1, 0, 0],
3177
           [2, 3, 4]])
3178

3179
    Reconstruct the input array from the unique values and inverse:
3180

3181
    >>> a = np.array([1, 2, 6, 4, 2, 3, 2])
3182
    >>> u, indices = np.unique(a, return_inverse=True)
3183
    >>> u
3184
    array([1, 2, 3, 4, 6])
3185
    >>> indices
3186
    array([0, 1, 4, 3, 1, 2, 1])
3187
    >>> u[indices]
3188
    array([1, 2, 6, 4, 2, 3, 2])
3189

3190
    Reconstruct the input values from the unique values and counts:
3191

3192
    >>> a = np.array([1, 2, 6, 4, 2, 3, 2])
3193
    >>> values, counts = np.unique(a, return_counts=True)
3194
    >>> values
3195
    array([1, 2, 3, 4, 6])
3196
    >>> counts
3197
    array([1, 3, 1, 1, 1])
3198
    >>> np.repeat(values, counts)
3199
    array([1, 2, 2, 2, 3, 4, 6])    # original order not preserved
3200

3201
    """
3202

3203
    if axis is None:
1✔
3204
        return _unique_1d(
1✔
3205
            ar, return_index, return_inverse, return_counts, equal_nan
3206
        )
3207

3208
    # axis was specified and not None
3209
    try:
1✔
3210
        ar = dpnp.moveaxis(ar, axis, 0)
1✔
3211
    except AxisError:
1✔
3212
        # this removes the "axis1" or "axis2" prefix from the error message
3213
        raise AxisError(axis, ar.ndim) from None
1✔
3214

3215
    # reshape input array into a contiguous 2D array
3216
    orig_sh = ar.shape
1✔
3217
    ar = ar.reshape(orig_sh[0], math.prod(orig_sh[1:]))
1✔
3218
    ar = dpnp.ascontiguousarray(ar)
1✔
3219

3220
    # build the indices for result array with unique values
3221
    sorted_indices = _unique_build_sort_indices(ar, orig_sh[0])
1✔
3222
    ar = ar[sorted_indices]
1✔
3223

3224
    if ar.size > 0:
1✔
3225
        mask = dpnp.empty_like(ar, dtype=dpnp.bool)
1✔
3226
        mask[:1] = True
1✔
3227
        mask[1:] = ar[1:] != ar[:-1]
1✔
3228

3229
        mask = mask.any(axis=1)
1✔
3230
    else:
3231
        # if the array is empty, then the mask should grab the first empty
3232
        # array as the unique one
3233
        mask = dpnp.ones_like(ar, shape=(ar.shape[0]), dtype=dpnp.bool)
1✔
3234
        mask[1:] = False
1✔
3235

3236
    # index the input array with the unique elements and reshape it into the
3237
    # original size and dimension order
3238
    ar = ar[mask]
1✔
3239
    ar = ar.reshape(mask.sum().asnumpy(), *orig_sh[1:])
1✔
3240
    ar = dpnp.moveaxis(ar, 0, axis)
1✔
3241

3242
    result = (ar,)
1✔
3243
    if return_index:
1✔
3244
        result += (sorted_indices[mask],)
1✔
3245
    if return_inverse:
1✔
3246
        imask = dpnp.cumsum(mask) - 1
1✔
3247
        inv_idx = dpnp.empty_like(mask, dtype=dpnp.intp)
1✔
3248
        inv_idx[sorted_indices] = imask
1✔
3249
        result += (inv_idx,)
1✔
3250
    if return_counts:
1✔
3251
        nonzero = dpnp.nonzero(mask)[0]
1✔
3252
        idx = dpnp.empty_like(
1✔
3253
            nonzero, shape=(nonzero.size + 1,), dtype=nonzero.dtype
3254
        )
3255
        idx[:-1] = nonzero
1✔
3256
        idx[-1] = mask.size
1✔
3257
        result += (idx[1:] - idx[:-1],)
1✔
3258

3259
    return _unpack_tuple(result)
1✔
3260

3261

3262
def vsplit(ary, indices_or_sections):
1✔
3263
    """
3264
    Split an array into multiple sub-arrays vertically (row-wise).
3265

3266
    Please refer to the :obj:`dpnp.split` documentation. ``vsplit``
3267
    is equivalent to ``split`` with ``axis=0``(default), the array
3268
    is always split along the first axis regardless of the array dimension.
3269

3270
    For full documentation refer to :obj:`numpy.vsplit`.
3271

3272
    Parameters
3273
    ----------
3274
    ary : {dpnp.ndarray, usm_ndarray}
3275
        Array to be divided into sub-arrays.
3276
    indices_or_sections : {int, sequence of ints}
3277
        If `indices_or_sections` is an integer, N, the array will be divided
3278
        into N equal arrays along the first axis. If such a split is not
3279
        possible, an error is raised.
3280
        If `indices_or_sections` is a sequence of sorted integers, the entries
3281
        indicate where along the first axis the array is split.
3282

3283
    Returns
3284
    -------
3285
    sub-arrays : list of dpnp.ndarray
3286
        A list of sub arrays. Each array is a view of the corresponding input
3287
        array.
3288

3289
    See Also
3290
    --------
3291
    :obj:`dpnp.split` : Split array into multiple sub-arrays of equal size.
3292

3293
    Examples
3294
    --------
3295
    >>> import dpnp as np
3296
    >>> x = np.arange(16.0).reshape(4, 4)
3297
    >>> x
3298
    array([[ 0.,  1.,  2.,  3.],
3299
           [ 4.,  5.,  6.,  7.],
3300
           [ 8.,  9., 10., 11.],
3301
           [12., 13., 14., 15.]])
3302
    >>> np.vsplit(x, 2)
3303
    [array([[0., 1., 2., 3.],
3304
            [4., 5., 6., 7.]]),
3305
     array([[ 8.,  9., 10., 11.],
3306
            [12., 13., 14., 15.]])]
3307
    >>> np.vsplit(x, np.array([3, 6]))
3308
    [array([[ 0.,  1.,  2.,  3.],
3309
            [ 4.,  5.,  6.,  7.],
3310
            [ 8.,  9., 10., 11.]]),
3311
     array([[12., 13., 14., 15.]]),
3312
     array([], shape=(0, 4), dtype=float64)]
3313

3314
    With a higher dimensional array the split is still along the first axis.
3315

3316
    >>> x = np.arange(8.0).reshape(2, 2, 2)
3317
    >>> x
3318
    array([[[0., 1.],
3319
            [2., 3.]],
3320
           [[4., 5.],
3321
            [6., 7.]]])
3322
    >>> np.vsplit(x, 2)
3323
    [array([[[0., 1.],
3324
             [2., 3.]]]),
3325
     array([[[4., 5.],
3326
             [6., 7.]]])]
3327

3328
    """
3329

3330
    dpnp.check_supported_arrays_type(ary)
1✔
3331
    if ary.ndim < 2:
1✔
3332
        raise ValueError("vsplit only works on arrays of 2 or more dimensions")
1✔
3333
    return split(ary, indices_or_sections, 0)
1✔
3334

3335

3336
def vstack(tup, *, dtype=None, casting="same_kind"):
1✔
3337
    """
3338
    Stack arrays in sequence vertically (row wise).
3339

3340
    :obj:`dpnp.row_stack` is an alias for :obj:`dpnp.vstack`.
3341
    They are the same function.
3342

3343
    For full documentation refer to :obj:`numpy.vstack`.
3344

3345
    Parameters
3346
    ----------
3347
    tup : {dpnp.ndarray, usm_ndarray}
3348
        The arrays must have the same shape along all but the first axis.
3349
        1-D arrays must have the same length.
3350
    dtype : str or dtype
3351
        If provided, the destination array will have this dtype.
3352
    casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
3353
        Controls what kind of data casting may occur. Defaults to 'same_kind'.
3354

3355
    Returns
3356
    -------
3357
    out : dpnp.ndarray
3358
        The array formed by stacking the given arrays, will be at least 2-D.
3359

3360
    See Also
3361
    --------
3362
    :obj:`dpnp.concatenate` : Join a sequence of arrays along an existing axis.
3363
    :obj:`dpnp.stack` : Join a sequence of arrays along a new axis.
3364
    :obj:`dpnp.hstack` : Stack arrays in sequence horizontally (column wise).
3365
    :obj:`dpnp.dstack` : Stack arrays in sequence depth wise (along third axis).
3366
    :obj:`dpnp.column_stack` : Stack 1-D arrays as columns into a 2-D array.
3367
    :obj:`dpnp.block` : Assemble an ndarray from nested lists of blocks.
3368
    :obj:`dpnp.split` : Split array into a list of multiple sub-arrays of equal
3369
                        size.
3370

3371
    Examples
3372
    --------
3373
    >>> import dpnp as np
3374
    >>> a = np.array([1, 2, 3])
3375
    >>> b = np.array([4, 5, 6])
3376
    >>> np.vstack((a, b))
3377
    array([[1, 2, 3],
3378
           [4, 5, 6]])
3379

3380
    >>> a = np.array([[1], [2], [3]])
3381
    >>> b = np.array([[4], [5], [6]])
3382
    >>> np.vstack((a, b))
3383
    array([[1],
3384
           [2],
3385
           [3],
3386
           [4],
3387
           [5],
3388
           [6]])
3389

3390
    """
3391

3392
    _check_stack_arrays(tup)
1✔
3393

3394
    arrs = dpnp.atleast_2d(*tup)
1✔
3395
    if not isinstance(arrs, list):
1✔
3396
        arrs = [arrs]
1✔
3397
    return dpnp.concatenate(arrs, axis=0, dtype=dtype, casting=casting)
1✔
3398

3399

3400
row_stack = vstack
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc