• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2020-2021 Huawei Technologies Co., Ltd
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ============================================================================
15"""array operations, the function docs are adapted from Numpy API."""
16import math
17import operator
18
19import numpy as onp
20
21from ..common import Tensor
22from ..common import dtype as mstype
23from ..ops import operations as P
24from ..ops import functional as F
25from ..ops.primitive import constexpr
26from ..nn.layer.basic import tril as nn_tril
27from ..nn.layer.basic import triu as nn_triu
28from .._c_expression import Tensor as Tensor_
29
30from .utils import _check_input_for_asarray, _deep_list, _deep_tensor_to_nparray, \
31    _check_input_tensor, _convert_64_to_32, _get_dtype_from_scalar, \
32    _expand, _to_tensor, _slice_along_axis, _callable
33from .utils_const import _raise_value_error, _empty, _max, _min, \
34    _check_same_type, _is_shape_empty, _check_shape, _check_dtype, _tile_size, _abs, \
35    _raise_type_error, _expanded_shape, _check_is_float, _iota, _type_convert, \
36    _canonicalize_axis, _list_comprehensions, _ceil, _tuple_slice, _raise_unimplemented_error, \
37    _tuple_setitem
38from .array_ops import ravel, concatenate, broadcast_arrays, reshape, broadcast_to, flip, \
39    apply_along_axis, where, moveaxis
40from .dtypes import nan, pi
41
42# According to official numpy reference, the dimension of a numpy array must be less
43# than 32
44MAX_NUMPY_DIMS = 32
45# All types that can be accepted as "array_like" parameters in graph mode.
46ARRAY_TYPES = (int, float, bool, list, tuple, Tensor)
47
48_reduce_min_keepdims = P.ReduceMin(True)
49_reduce_max_keepdims = P.ReduceMax(True)
50_reduce_mean_keepdims = P.ReduceMean(True)
51
52
53def array(obj, dtype=None, copy=True, ndmin=0):
54    """
55    Creates a tensor.
56
57    This function creates tensors from an array-like object.
58
59    Args:
60        obj (Union[int, float, bool, list, tuple]): Input data, in any form that
61            can be converted to a `Tensor`. This includes Tensor, list, tuple and numbers.
62        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype, can
63            be in format of np.int32, or \'int32\'. If dtype is :class:`None`, the data type
64            of the new tensor will be inferred from obj. Default is :class:`None`.
65        copy (bool): If `True`, then the object is copied. Otherwise, a copy will
66            only be made if necessary. Default: `True`.
67        ndmin (int): Specifies the minimum number of dimensions that the resulting
68            tensor should have. Ones will be pre-pended to the shape as needed to
69            meet this requirement. Default: 0
70
71    Returns:
72        Tensor, generated tensor with the specified dtype.
73
74    Raises:
75        TypeError: If input arguments have types not specified above.
76        ValueError: If input `obj` has different sizes at different dimensions.
77
78    Supported Platforms:
79        ``Ascend`` ``GPU`` ``CPU``
80
81    Examples:
82        >>> import mindspore.numpy as np
83        >>> print(np.array([1,2,3]))
84        [1 2 3]
85    """
86    if dtype is not None:
87        dtype = _check_dtype(dtype)
88    res = asarray(obj, dtype)
89
90    if ndmin > res.ndim:
91        if res.size == 0:
92            _raise_value_error("Empty tensor cannot be expanded beyond the current dimension.")
93        res = _expand(res, ndmin)
94
95    if copy and isinstance(obj, Tensor):
96        res = copy_(res)
97    elif dtype is not None and dtype != res.dtype:
98        res = res.astype(dtype)
99
100    return res
101
102
103@constexpr
104def asarray_const(a, dtype=None):
105    """Converts the input to tensor. Note here `a` cannot be tensor itself."""
106    _check_input_for_asarray(a)
107
108    if dtype is not None:
109        dtype = _check_dtype(dtype)
110
111    if isinstance(a, (float, int, bool)) and dtype is None:
112        dtype = _get_dtype_from_scalar(a)
113
114    if isinstance(a, (list, tuple)):
115        # Convert all tuple/nested tuples to lists
116        a = _deep_list(a)
117        # Convert all tensor sub-elements to numpy arrays
118        a = _deep_tensor_to_nparray(a)
119        a = onp.asarray(a)
120        if a.dtype is onp.dtype('object'):
121            raise ValueError('Input array must have the same size across all dimensions.')
122        # If dtype is not specified, we keep consistent with numpy decision
123        # only exceptions are: we use int/float32
124        if dtype is None:
125            dtype = mstype.pytype_to_dtype(a.dtype)
126            if dtype == mstype.float64:
127                dtype = mstype.float32
128            elif dtype == mstype.int64:
129                dtype = mstype.int32
130
131    if isinstance(a, onp.ndarray) and dtype is None:
132        if a.dtype is onp.dtype('object'):
133            raise TypeError(f"For Tensor conversion, the input_data is {a} that contains unsupported element.")
134        dtype = mstype.pytype_to_dtype(a.dtype)
135        a = Tensor.from_numpy(a)
136
137    return Tensor(a, dtype=dtype)
138
139
140def asarray(a, dtype=None):
141    """
142    Converts the input to tensor.
143
144    This function converts tensors from an array-like object.
145
146    Args:
147        a (Union[int, float, bool, list, tuple, Tensor]): Input data, in any form that can
148            be converted to a `Tensor`. This includes Tensor, list, tuple and numbers.
149        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype, can
150            be in format of np.int32, or \'int32\'. If dtype is :class:`None`, the data type
151            of the new tensor will be inferred from obj. Default is :class:`None`.
152
153    Returns:
154        Tensor, generated tensor with the specified dtype.
155
156    Raises:
157        TypeError: If input arguments have types not specified above.
158        ValueError: If input `a` has different sizes at different dimensions.
159
160    Supported Platforms:
161        ``Ascend`` ``GPU`` ``CPU``
162
163    Examples:
164        >>> import mindspore.numpy as np
165        >>> print(np.asarray([1,2,3]))
166        [1 2 3]
167    """
168    if dtype is not None:
169        dtype = _check_dtype(dtype)
170    if isinstance(a, Tensor):
171        if dtype is None or dtype == a.dtype:
172            return a
173        return a.astype(dtype)
174    return asarray_const(a, dtype)
175
176
177@constexpr
178def asfarray_const(a, dtype=mstype.float32):
179    """Converts the input to tensor. Note here `a` cannot be tensor itself."""
180    _check_input_for_asarray(a)
181    if isinstance(a, (list, tuple)):
182        # Convert all tuple/nested tuples to lists
183        a = _deep_list(a)
184        # Convert all tensor sub-elements to numpy arrays
185        a = _deep_tensor_to_nparray(a)
186        a = onp.asarray(a)
187        if a.dtype is onp.dtype('object'):
188            raise ValueError(f"For Tensor conversion, the input_data is {a} that contains unsupported element.")
189        a = Tensor.from_numpy(a)
190
191    return Tensor(a, dtype)
192
193
194def asfarray(a, dtype=mstype.float32):
195    """
196    Similar to asarray, converts the input to a float tensor.
197
198    If non-float dtype is defined, this function will return a float32 tensor instead.
199
200    Args:
201        a (Union[int, float, bool, list, tuple, Tensor]): Input data, in any form that can
202            be converted to a `Tensor`. This includes Tensor, list, tuple and numbers.
203        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype, can
204            be in format of np.int32, or \'int32\'. If dtype is :class:`None`, the data type
205            of the new tensor will be inferred from `a`. Default is :class:`mindspore.float32`.
206
207
208    Returns:
209        Tensor, generated tensor with the specified float dtype.
210
211    Raises:
212        TypeError: If input arguments have types not specified above.
213        ValueError: If input `a` has different sizes at different dimensions.
214
215    Supported Platforms:
216        ``Ascend`` ``GPU`` ``CPU``
217
218    Examples:
219        >>> import mindspore.numpy as np
220        >>> print(np.asfarray([1,2,3]))
221        [1. 2. 3.]
222    """
223    if dtype is None:
224        return asarray(a)
225
226    dtype = _check_dtype(dtype)
227    if dtype not in (mstype.float16, mstype.float32, mstype.float64):
228        dtype = mstype.float32
229
230    if isinstance(a, Tensor):
231        return a.astype(dtype)
232
233    return asfarray_const(a, dtype)
234
235
236def copy_(a):
237    """
238    Returns a tensor copy of the given object.
239
240    Args:
241        a (Union[int, float, bool, list, tuple, Tensor]): Input data, in any form that can
242            be converted to a Tensor. This includes Tensor, list, tuple and numbers.
243
244    Returns:
245        Tensor, has the same data as `a`.
246
247    Raises:
248        TypeError: If input `a` has type not specified above.
249        ValueError: If input `a` has different sizes at different dimensions.
250
251    Supported Platforms:
252        ``Ascend`` ``GPU`` ``CPU``
253
254    Examples:
255        >>> import mindspore.numpy as np
256        >>> x = np.ones((2,2))
257        >>> print(np.copy(x))
258        [[1. 1.]
259         [1. 1.]]
260    """
261    a = asarray(a)
262    return a.copy()
263
264
265def ones(shape, dtype=mstype.float32):
266    """
267    Returns a new tensor of given shape and type, filled with ones.
268
269    Args:
270        shape (Union[int, tuple, list]): the shape of the new tensor.
271        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype.
272            Default is :class:`mstype.float32`.
273
274    Returns:
275        Tensor, with the designated `shape` and `dtype`, filled with ones.
276
277    Raises:
278        TypeError: If input arguments have types not specified above.
279        ValueError: If `shape` entries have values :math:`< 0`.
280
281    Supported Platforms:
282        ``Ascend`` ``GPU`` ``CPU``
283
284    Examples:
285        >>> import mindspore.numpy as np
286        >>> print(np.ones((2,2)))
287        [[1. 1.]
288        [1. 1.]]
289    """
290    shape = _check_shape(shape)
291    dtype = _check_dtype(dtype)
292    if _is_shape_empty(shape):
293        return full(shape, 1.0, dtype)
294    output = F.fill(dtype, shape, 1)
295    return output
296
297
298def zeros(shape, dtype=mstype.float32):
299    """
300    Returns a new tensor of given shape and type, filled with zeros.
301
302    Args:
303        shape (Union[int, tuple, list]): the shape of the new tensor.
304        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype.
305            Default is :class:`mstype.float32`.
306
307    Returns:
308        Tensor, with the designated `shape` and `dtype`, filled with zeros.
309
310    Raises:
311        TypeError: If input arguments have types not specified above.
312        ValueError: If `shape` entries have values :math:`< 0`.
313
314    Supported Platforms:
315        ``Ascend`` ``GPU`` ``CPU``
316
317    Examples:
318        >>> import mindspore.numpy as np
319        >>> print(np.zeros((2,2)))
320        [[0. 0.]
321        [0. 0.]]
322    """
323    shape = _check_shape(shape)
324    dtype = _check_dtype(dtype)
325    if _is_shape_empty(shape):
326        return full(shape, 0.0, dtype)
327    output = F.fill(dtype, shape, 0)
328    return output
329
330
331def full(shape, fill_value, dtype=None):
332    """
333    Returns a new tensor of given shape and type, filled with `fill_value`.
334
335    Args:
336        shape (Union[int, tuple(int), list(int)]): Shape of the new tensor, e.g.,
337            :math:`(2, 3)` or :math:`2`.
338        fill_value (Union[int, float, bool, list, tuple]): Scalar or array_like
339            fill value.
340        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype,
341            if `dtype` is :class:`None`, the data type of the new tensor will be inferred from
342            `fill_value`. Default is :class:`None`.
343
344    Returns:
345        Tensor, with the designated shape and dtype, filled with `fill_value`.
346
347    Raises:
348        TypeError: If input arguments have types not specified above.
349        ValueError: If `shape` has entries < 0.
350
351    Supported Platforms:
352        ``Ascend`` ``GPU`` ``CPU``
353
354    Examples:
355        >>> import mindspore.numpy as np
356        >>> print(np.full((2,2), True))
357        [[True True]
358        [True True]]
359    """
360    shape = _check_shape(shape)
361    if not isinstance(fill_value, ARRAY_TYPES):
362        _raise_type_error("fill value should be int, float, bool, list, tuple, Tensor, but got", fill_value)
363    if dtype is not None:
364        dtype = _check_dtype(dtype)
365    else:
366        if isinstance(fill_value, (int, float, bool)):
367            dtype = _get_dtype_from_scalar(fill_value)
368        if isinstance(fill_value, Tensor):
369            dtype = fill_value.dtype
370
371    if not _is_shape_empty(shape):
372        if isinstance(fill_value, (int, float, bool)):
373            return F.fill(dtype, shape, fill_value)
374        if isinstance(fill_value, (list, tuple)):
375            fill_value = asarray_const(fill_value)
376        return broadcast_to(fill_value, shape)
377    # if shape contains zero, use c.Tensor()
378    return _convert_64_to_32(empty_compile(dtype, shape))
379
380
381def arange(start, stop=None, step=None, dtype=None):
382    """
383    Returns evenly spaced values within a given interval.
384
385    Args:
386        start(Union[int, float]): Start of interval. The interval includes this value.
387            When `stop` is provided as a position argument, `start` must be given, when `stop`
388            is a normal argument, `start` can be optional, and default is 0.
389            Please see additional examples below.
390        stop(Union[int, float], optional): End of interval. The interval does not
391            include this value, except in some cases where `step` is not an integer
392            and floating point round-off affects the length of out.
393        step(Union[int, float], optional): Spacing between values. For any output
394            `out`, this is the distance between two adjacent values, :math:`out[i+1] - out[i]`.
395            The default step size is 1. If `step` is specified as a position argument,
396            `start` must also be given.
397        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype.
398            If dtype is None, the data type of the new tensor will be inferred from start,
399            stop and step. Default is None.
400
401    Returns:
402        Tensor with evenly spaced values.
403
404    Raises:
405        TypeError(PyNative Mode): If input arguments have types not specified above,
406            or arguments are not given in the correct orders specified above.
407        RuntimeError(Graph Mode): The inputs that lead to TypeError in Pynative Mode
408            will lead to RuntimeError in Graph Mode.
409
410    Supported Platforms:
411        ``Ascend`` ``GPU`` ``CPU``
412
413    Examples:
414        >>> import mindspore.numpy as np
415        >>> print(np.arange(0, 5, 1))
416        [0 1 2 3 4]
417        >>> print(np.arange(3))
418        [0 1 2]
419        >>> print(np.arange(start=0, stop=3))
420        [0 1 2]
421        >>> print(np.arange(0, stop=3, step=0.5))
422        [0.  0.5 1.  1.5 2.  2.5]
423        >>> print(np.arange(stop=3)) # This will lead to TypeError
424    """
425    # This implementation was inspired by jax.numpy.arange
426    # infer the dtype
427    if dtype is None:
428        dtype = _get_dtype_from_scalar(start, stop, step)
429    if stop is None and step is None: # (start, stop, step) -> (0, start, 1)
430        num = _ceil(start)
431        out = _iota(mstype.float32, num)
432    elif step is None:  # (start, stop, step) -> (start, stop, 1)
433        num = _ceil(stop - start)
434        out = _iota(mstype.float32, num) + start
435    elif stop is None: # (start, stop, step) -> (0, start, step)
436        num = _ceil((start + 0.0) / step)
437        out = _iota(mstype.float32, num) * step
438    else:
439        num = _ceil((stop - start + 0.0) / step)
440        out = _iota(mstype.float32, num) * step + start
441    return out.astype(dtype)
442
443
444def _type_checking_for_xspace(start, stop, num, endpoint, dtype):
445    """utility parameter checking function for linspace, logspace, geomspace."""
446    if not isinstance(start, ARRAY_TYPES):
447        _raise_type_error("start should be int, float, bool, list, tuple, Tensor, but got", start)
448    if not isinstance(stop, ARRAY_TYPES):
449        _raise_type_error("end should be int, float, bool, list, tuple, Tensor, but got", stop)
450    if not isinstance(start, Tensor):
451        start = _type_convert(Tensor, start).astype(mstype.float32)
452    if not isinstance(stop, Tensor):
453        stop = _type_convert(Tensor, stop).astype(mstype.float32)
454    if not isinstance(num, int):
455        _raise_type_error("num should be an integer, but got ", num)
456    if not isinstance(endpoint, bool):
457        _raise_type_error("endpoint should be an boolean, but got ", endpoint)
458    if dtype is not None:
459        dtype = _check_dtype(dtype)
460    else:
461        dtype = mstype.float32
462    start, stop = broadcast_arrays(start, stop)
463    return start, stop, num, endpoint, dtype
464
465
466def _compute_shapes(start, axis, num, endpoint):
467    """Computes shapes for local variables for np.linspace"""
468    bounds_shape = start.shape
469    bounds_shape = _tuple_slice(bounds_shape, None, axis) + (1,) + _tuple_slice(bounds_shape, axis, None)
470    iota_shape = _list_comprehensions(start.ndim+1, 1, True)
471    iota_shape = _tuple_slice(iota_shape, None, axis) + (num,) + _tuple_slice(iota_shape, axis+1, None)
472    num_tensor = _type_convert(Tensor, num).astype(mstype.float32)
473    div = (num_tensor - 1) if endpoint else num_tensor
474    return bounds_shape, iota_shape, div
475
476
477def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0):
478    """
479    Returns evenly spaced values within a given interval.
480
481    Args:
482        start (Union[int, list(int), tuple(int), tensor]): The starting value of the sequence.
483        stop (Union[int, list(int), tuple(int), tensor]): The end value of the sequence,
484            unless `endpoint` is set to False. In that case, the sequence consists
485            of all but the last of `num + 1` evenly spaced samples, so that `stop`
486            is excluded.  Note that the step size changes when `endpoint` is False.
487        num (int, optional): Number of samples to generate. Default is 50.
488        endpoint (bool, optional): If True, `stop` is the last sample. Otherwise, it is
489            not included. Default is True.
490        retstep (bool, optional): If True, return (`samples`, `step`), where `step` is
491            the spacing between samples.
492        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype,
493            If `dtype` is None, infer the data type from other input arguments. Default is None.
494        axis (int, optional): The axis in the result to store the samples. Relevant
495            only if start or stop are array-like.  By default, the samples will
496            be along a new axis inserted at the beginning. Use -1 to get an axis at the end.
497            Default is 0.
498
499    Returns:
500        Tensor, with `num` equally spaced samples in the closed interval
501        :math:`[start, stop]` or the half-open interval :math:`[start, stop)`
502        (depending on whether `endpoint` is True or False).
503
504        Step, the size of spacing between samples, only returned if `retstep` is True.
505
506    Raises:
507        TypeError: If input arguments have types not specified above.
508
509    Supported Platforms:
510        ``Ascend`` ``GPU`` ``CPU``
511
512    Examples:
513        >>> import mindspore.numpy as np
514        >>> print(np.linspace(0, 5, 6))
515        [0. 1. 2. 3. 4. 5.]
516    """
517    # This implementation was inspired by jax.numpy.linspace and numpy.linspace
518    start, stop, num, endpoint, dtype = _type_checking_for_xspace(start, stop, num, endpoint, dtype)
519    axis = _canonicalize_axis(axis, start.ndim+1)
520    if not isinstance(retstep, bool):
521        _raise_type_error("retstep should be an boolean, but got ", retstep)
522    bounds_shape, iota_shape, div = _compute_shapes(start, axis, num, endpoint)
523    out = None
524    delta = None
525    if num > 1:
526        delta = (stop - start) / div
527        # This is similar to how numpy and jax compute linspace
528        start_expand = reshape(start, bounds_shape)
529        incremental_expand = reshape(_iota(mstype.float32, num), iota_shape)
530        delta_expand = reshape(delta, bounds_shape)
531        start_expand, incremental_expand, delta_expand = broadcast_arrays(
532            start_expand, incremental_expand, delta_expand)
533        out = start_expand + (incremental_expand * delta_expand)
534        # recover endpoint
535        if endpoint:
536            out = moveaxis(out, axis, 0)
537            out[-1] = stop
538            out = moveaxis(out, 0, axis)
539    elif num == 1:
540        delta = nan if endpoint else stop - start
541        out = reshape(start, bounds_shape)
542    else:  # num == 0
543        _raise_value_error("cannot support Tensor with num=0.")
544    if retstep:
545        return out.astype(dtype), delta
546    return out.astype(dtype)
547
548
549def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0):
550    """
551    Returns numbers spaced evenly on a log scale.
552
553    In linear space, the sequence starts at base ** start (base to the power of
554    start) and ends with base ** stop (see endpoint below).
555
556    Args:
557        start (Union[int, list(int), tuple(int), tensor]): ``base ** start`` is the starting
558            value of the sequence.
559        stop (Union[int, list(int), tuple(int), tensor]): ``base ** stop`` is the final value of
560            the sequence, unless `endpoint` is False. In that case, ``num + 1`` values are spaced
561            over the interval in log-space, of which all but the last (a sequence of length num)
562            are returned.
563        num (int, optional): Number of samples to generate. Default is 50.
564        endpoint (bool, optional): If True, `stop` is the last sample. Otherwise, it is
565            not included. Default is True.
566        base (Union[int, float], optional): The base of the log space. The step size
567            between the elements in :math:`ln(samples) / ln(base)` (or :math:`log_{base}(samples)`)
568            is uniform. Default is 10.0.
569        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype.
570            If `dtype` is None, infer the data type from other input arguments. Default is None.
571        axis (int, optional): The axis in the result to store the samples. Relevant
572            only if start or stop is array-like.  By default, the samples will
573            be along a new axis inserted at the beginning. Use -1 to get an axis at the end.
574            Default is 0.
575
576    Returns:
577        Tensor, equally spaced on a log scale.
578
579    Raises:
580        TypeError: If input arguments have types not specified above.
581
582    Supported Platforms:
583        ``Ascend`` ``GPU`` ``CPU``
584
585    Examples:
586        >>> import mindspore.numpy as np
587        >>> print(np.logspace(0, 5, 6, base=2.0))
588        [ 1.  2.  4.  8. 16. 32.]
589    """
590    # This implementation was inspired by jax.numpy.linspace and numpy.linspace
591    start, stop, num, endpoint, dtype = _type_checking_for_xspace(start, stop, num, endpoint, dtype)
592    axis = _canonicalize_axis(axis, start.ndim+1)
593    if not isinstance(base, (int, float, bool)):
594        _raise_type_error("base should be a number, but got ", base)
595    linspace_res = linspace(start, stop, num, endpoint=endpoint, retstep=False, dtype=None, axis=axis)
596    return F.tensor_pow(base, linspace_res).astype(dtype)
597
598
599def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
600    """
601    Returns numbers spaced evenly on a log scale (a geometric progression).
602
603    This is similar to logspace, but with endpoints specified directly. Each output sample
604    is a constant multiple of the previous.
605
606    Args:
607        start (Union[int, list(int), tuple(int), tensor]): The starting value of the sequence.
608        stop (Union[int, list(int), tuple(int), tensor]): The final value of the sequence,
609            unless endpoint is False. In that case, num + 1 values are spaced over the
610            interval in log-space, of which all but the last (a sequence of length num) are
611            returned.
612        num (int, optional): Number of samples to generate. Default is 50.
613        endpoint (bool, optional): If True, `stop` is the last sample. Otherwise, it is
614            not included. Default is True.
615        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype, can
616            be in format of np.float32, or `float32`.If `dtype` is None, infer the data
617            type from other input arguments. Default is None.
618        axis (int, optional): The axis in the result to store the samples. Relevant
619            only if start or stop is array-like.  By default (0), the samples will
620            be along a new axis inserted at the beginning. Use -1 to get an axis at the end.
621            Default is 0.
622
623    Returns:
624        Tensor, with samples equally spaced on a log scale.
625
626    Raises:
627        TypeError: If input arguments have types not specified above.
628
629    Supported Platforms:
630        ``Ascend`` ``GPU`` ``CPU``
631
632    Examples:
633        >>> output = np.geomspace(1, 256, num=9)
634        >>> print(output)
635        [  1.   2.   4.   8.  16.  32.  64. 128. 256.]
636        >>> output = np.geomspace(1, 256, num=8, endpoint=False)
637        >>> print(output)
638        [  1.   2.   4.   8.  16.  32.  64. 128.]
639    """
640    start, stop, num, endpoint, dtype = _type_checking_for_xspace(start, stop, num, endpoint, dtype)
641    axis = _canonicalize_axis(axis, start.ndim+1)
642    root = num
643    if endpoint:
644        root -= 1
645    bases = F.tensor_pow(F.tensor_div(stop, start), asarray_const(1./(root)))
646    exponents = linspace(zeros(F.shape(bases)), F.fill(F.dtype(bases), F.shape(bases), root),
647                         num, endpoint=endpoint, dtype=dtype, axis=axis)
648    shape = F.shape(bases)
649    axis = axis + F.rank(bases) + 1 if axis < 0 else axis
650    expanded_shape = _tuple_slice(shape, None, axis) + (1,) + _tuple_slice(shape, axis, None)
651    bases = F.reshape(bases, expanded_shape)
652    start = F.reshape(start, expanded_shape)
653    res = F.tensor_mul(F.tensor_pow(bases, exponents), start)
654    if dtype is not None:
655        res = F.cast(res, dtype)
656    return res
657
658
659def eye(N, M=None, k=0, dtype=mstype.float32):
660    """
661    Returns a 2-D tensor with ones on the diagonal and zeros elsewhere.
662
663    Args:
664        N (int): Number of rows in the output, must be larger than 0.
665        M (int, optional): Number of columns in the output. If is :class:`None`, defaults to `N`,
666            if defined, must be larger than 0. Deault is :class:`None`.
667        k (int, optional): Index of the diagonal: 0 (the default) refers to the main
668            diagonal, a positive value refers to an upper diagonal, and a negative value
669            to a lower diagonal. Default is 0.
670        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype.
671            Default is mstype.float32.
672
673    Returns:
674        A tensor of shape (N, M). A tensor where all elements are equal to zero,
675        except for the k-th diagonal, whose values are equal to one.
676
677    Raises:
678        TypeError: If input arguments have types not specified above.
679
680    Supported Platforms:
681        ``Ascend`` ``GPU`` ``CPU``
682
683    Examples:
684        >>> import mindspore.numpy as np
685        >>> print(np.eye(2, 2))
686        [[1. 0.]
687        [0. 1.]]
688    """
689    dtype = _check_dtype(dtype)
690    if M is None:
691        M = N
692    if not (isinstance(M, int) and isinstance(N, int) and isinstance(k, int)):
693        _raise_type_error("Input tensor dimensions should be integers.")
694    out = None
695    if N == 0 or M == 0:
696        # Fill the shape with any value is fine.
697        return full((N, M), 0, dtype)
698
699    out = F.eye(N, M, dtype)
700
701    if k >= M or k <= -N:
702        return full((N, M), 0, dtype)
703    if k != 0:
704        out = out.astype(mstype.float32)
705        if k > 0:
706            out_left = full((N, k), 0, dtype)
707            out_right = out[..., 0:M-k:1]
708            return concatenate((out_left, out_right), 1).astype(dtype)
709        if k < 0:
710            out_upper = full((-k, M), 0, dtype)
711            out_lower = out[0:N+k:1, ...]
712            return concatenate((out_upper, out_lower), 0).astype(dtype)
713    return out
714
715
716def identity(n, dtype=mstype.float32):
717    """
718    Returns the identity tensor.
719
720    Args:
721        n (int): Number of rows and columns in the output, must be larger than 0.
722        dtype (Union[:class:`mindspore.dtype`, str], optional): Designated tensor dtype,
723            default is :class:`mstype.float32`.
724
725    Returns:
726        A tensor of shape `(n, n)`, where all elements are equal to zero,
727        except for the diagonal, whose values are equal to one.
728
729    Supported Platforms:
730        ``Ascend`` ``GPU`` ``CPU``
731
732    Raises:
733        TypeError: If input arguments have types not specified above.
734
735    Examples:
736        >>> import mindspore.numpy as np
737        >>> print(np.identity(2))
738        [[1. 0.]
739        [0. 1.]]
740    """
741    if not isinstance(n, int):
742        _raise_type_error("Input tensor dimensions should be integers.")
743    dtype = _check_dtype(dtype)
744    return eye(n, dtype=dtype)
745
746
747@constexpr
748def empty_compile(dtype, shape):
749    """Returns an empty Tensor."""
750    return Tensor_(dtype, shape)
751
752
753def empty(shape, dtype=mstype.float32):
754    """
755    Returns a new array of given shape and type, without initializing
756    entries.
757
758    Note:
759        Numpy argument `order` is not supported.
760        Object arrays are not supported.
761
762    Args:
763        shape (Union[int, tuple(int)]): Shape of the empty array, e.g.,
764            (2, 3) or 2.
765        dtype (:class:`mindspore.dtype`, optional): Desired output data-type for the
766            array, e.g, mstype.int8. Default is mstype.float32.
767
768    Returns:
769        Tensor, array of uninitialized (arbitrary) data of the given
770        shape and dtype.
771
772    Raises:
773        TypeError: if the input shape or dtype is invalid.
774
775    Supported Platforms:
776        ``Ascend`` ``GPU`` ``CPU``
777
778    Examples:
779        >>> import mindspore.numpy as np
780        >>> output = np.empty((2, 3))
781        >>> print(output)
782        # result may vary
783        Tensor(shape=[2, 3], dtype=Float32, value=
784        <uninitialized>)
785    """
786    shape = _check_shape(shape)
787    dtype = _check_dtype(dtype)
788    return empty_compile(dtype, shape)
789
790
791def _get_shape(array_like):
792    """Returns the shape of the array like object."""
793    if isinstance(array_like, Tensor):
794        return array_like.shape
795    return asarray_const(array_like).shape
796
797
798def _get_dtype(array_like):
799    """Returns the data type of the array like object."""
800    if isinstance(array_like, Tensor):
801        return array_like.dtype
802    return asarray_const(array_like).dtype
803
804
805def _x_like(prototype, dtype, shape, constructor, fill_value=None):
806    """
807    Returns a tensor with the same shape and type as prototype,
808    using constructor.
809    """
810    if not isinstance(prototype, ARRAY_TYPES):
811        _raise_type_error("prototype should be int, float, bool, list, tuple, Tensor, but got", prototype)
812    dtype_out = dtype
813    shape_out = shape
814    if dtype_out is None:
815        dtype_out = _get_dtype(prototype)
816    if shape_out is None or isinstance(shape_out, (list, tuple)) and not shape_out:
817        shape_out = _get_shape(prototype)
818    if fill_value is not None:
819        return constructor(shape_out, fill_value, dtype_out)
820    return constructor(shape_out, dtype_out)
821
822
823def empty_like(prototype, dtype=None, shape=None):
824    """
825    Returns a new array with the same shape and type as a given array.
826
827    Note:
828        Input array must have the same size across a dimension.
829        If `prototype` is not a Tensor, dtype is float32 by default if not provided.
830
831    Args:
832        prototype (Union[Tensor, list, tuple]): The shape and data-type of `prototype`
833            define these same attributes of the returned array.
834        dtype (:class:`mindspore.dtype`, optional): Overrides the data type of the
835            result.
836        shape (int or sequence of ints, optional): Overrides the shape
837            of the result.
838
839    Returns:
840        Tensor, array of uninitialized (arbitrary) data with the same
841        shape and type as `prototype`.
842
843    Raises:
844        ValueError: if `prototype` is not a Tensor, list or tuple.
845
846    Supported Platforms:
847        ``Ascend`` ``GPU`` ``CPU``
848
849    Examples:
850        >>> import mindspore.numpy as np
851        >>> a = np.ones((4,1,2))
852        >>> output = np.empty_like(a)
853        >>> print(output)
854        # result may vary
855        Tensor(shape=[4, 1, 2], dtype=Float32, value=
856        <uninitialized>)
857    """
858    return _x_like(prototype, dtype, shape, empty)
859
860
861def ones_like(a, dtype=None, shape=None):
862    """
863    Returns an array of ones with the same shape and type as a given array.
864
865    Note:
866        Input array must have the same size across a dimension.
867        If `a` is not a Tensor, dtype is float32 by default if not provided.
868
869    Args:
870        a (Union[Tensor, list, tuple]): The shape and data-type of a define these same
871            attributes of the returned array.
872        dtype (:class:`mindspore.dtype`, optional): Overrides the data type of the
873            result.
874        shape (int or sequence of ints, optional): Overrides the shape
875            of the result.
876
877    Returns:
878        Tensor, array of ones with the same shape and type as `a`.
879
880    Raises:
881        ValueError: if `a` is not a Tensor, list or tuple.
882
883    Supported Platforms:
884        ``Ascend`` ``GPU`` ``CPU``
885
886    Examples:
887        >>> import mindspore.numpy as np
888        >>> a = np.ones((4,1,2))
889        >>> output = np.ones_like(a)
890        >>> print(output)
891        [[[1. 1.]]
892        [[1. 1.]]
893        [[1. 1.]]
894        [[1. 1.]]]
895    """
896    return _x_like(a, dtype, shape, ones)
897
898
899def zeros_like(a, dtype=None, shape=None):
900    """
901    Returns an array of zeros with the same shape and type as a given array.
902
903    Note:
904        Input array must have the same size across a dimension.
905        If `a` is not a Tensor, dtype is float32 by default if not provided.
906
907    Args:
908        a (Union[Tensor, list, tuple]): The shape and data-type of a define these same
909            attributes of the returned array.
910        dtype (:class:`mindspore.dtype`, optional): Overrides the data type of the
911            result.
912        shape (int or sequence of ints, optional): Overrides the shape
913            of the result.
914
915    Returns:
916        Tensor, array of zeros with the same shape and type as `a`.
917
918    Raises:
919        ValueError: if `a` is not a Tensor, list or tuple.
920
921    Supported Platforms:
922        ``Ascend`` ``GPU`` ``CPU``
923
924    Examples:
925        >>> import mindspore.numpy as np
926        >>> a = np.ones((4,1,2))
927        >>> output = np.zeros_like(a)
928        >>> print(output)
929        [[[0. 0.]]
930        [[0. 0.]]
931        [[0. 0.]]
932        [[0. 0.]]]
933    """
934    return _x_like(a, dtype, shape, zeros)
935
936
937def full_like(a, fill_value, dtype=None, shape=None):
938    """
939    Returns a full array with the same shape and type as a given array.
940
941    Note:
942        Input array must have the same size across a dimension.
943        If `a` is not a Tensor, dtype is float32 by default if not provided.
944
945    Args:
946        a (Union[Tensor, list, tuple]): The shape and data-type of `a` define these same
947            attributes of the returned array.
948        fill_value (scalar): Fill value.
949        dtype (:class:`mindspore.dtype`, optional): Overrides the data type of the
950            result.
951        shape (int or sequence of ints, optional): Overrides the shape
952            of the result.
953
954    Returns:
955        Tensor, array of fill_value with the same shape and type as `a`.
956
957    Raises:
958        ValueError: if `a` is not a Tensor, list or tuple.
959
960    Supported Platforms:
961        ``Ascend`` ``GPU`` ``CPU``
962
963    Examples:
964        >>> import mindspore.numpy as np
965        >>> a = np.ones((4,1,2))
966        >>> output = np.full_like(a, 0.5)
967        >>> print(output)
968        [[[0.5 0.5]]
969        [[0.5 0.5]]
970        [[0.5 0.5]]
971        [[0.5 0.5]]]
972    """
973    return _x_like(a, dtype, shape, full, fill_value=fill_value)
974
975
976def tri(N, M=None, k=0, dtype=mstype.float32):
977    """
978    Returns a tensor with ones at and below the given diagonal and zeros elsewhere.
979
980    Args:
981        N(int): Number of rows in the array.
982        M(int, optional): Number of columns in the array. By default, `M` is taken
983            equal to N.
984        k(int, optional): The sub-diagonal at and below which the array is filled.
985            :math:`k = 0` is the main diagonal, while :math:`k < 0` is below it, and :math:`k > 0` is above.
986            The default is 0.
987        dtype(:class:`mindspore.dtype`, optional): Data type of the returned array. The default
988            is mstype.float32.
989
990    Returns:
991        Tensor with shape `(N, M)`, with its lower triangle filled with
992        ones and zeros elsewhere; in other words :math:`T[i,j] = 1` for :math:`j <= i + k`,
993        0 otherwise.
994
995    Raises:
996        TypeError: If input arguments have types not specified above.
997
998    Supported Platforms:
999        ``Ascend`` ``GPU`` ``CPU``
1000
1001    Examples:
1002        >>> import mindspore.numpy as np
1003        >>> output = np.tri(3, 3, 1)
1004        >>> print(output)
1005        [[1. 1. 0.]
1006        [1. 1. 1.]
1007        [1. 1. 1.]]
1008    """
1009    if M is None:
1010        M = N
1011    return nn_tril((N, M), dtype, k)
1012
1013
1014def tril(m, k=0):
1015    """
1016    Returns a lower triangle of a tensor.
1017
1018    Returns a copy of a tensor with elements above the `k-th` diagonal zeroed.
1019
1020    Args:
1021        m (Union[Tensor, list, tuple]): The shape and data-type of `m` define these same
1022            attributes of the returned tensor.
1023        k (int, optional): Diagonal above which to zero elements. :math:`k = 0` (the default)
1024            is the main diagonal, :math:`k < 0` is below it and :math:`k > 0` is above.
1025
1026    Returns:
1027        Lower triangle of `m`, of same shape and data-type as `m`.
1028
1029    Supported Platforms:
1030        ``Ascend`` ``GPU`` ``CPU``
1031
1032    Raises:
1033        TypeError: If input arguments have types not specified above.
1034        ValueError: If input `m`\'s rank :math:`< 1`.
1035
1036    Examples:
1037        >>> import mindspore.numpy as np
1038        >>> output = np.tril(np.ones((3, 3)))
1039        >>> print(output)
1040        [[1. 0. 0.]
1041        [1. 1. 0.]
1042        [1. 1. 1.]]
1043    """
1044    if not isinstance(m, Tensor):
1045        m = asarray_const(m)
1046    dtype = m.dtype
1047    m = m.astype(mstype.float32)
1048    assist = nn_tril(m.shape, mstype.float32, k)
1049    return F.tensor_mul(assist, m).astype(dtype)
1050
1051
1052def triu(m, k=0):
1053    """
1054    Returns an upper triangle of a tensor.
1055
1056    Returns a copy of a tensor with elements below the `k-th` diagonal zeroed.
1057
1058    Args:
1059        m (Union[Tensor, list, tuple]): The shape and data-type of `m` define these same
1060            attributes of the returned tensor.
1061        k (int, optional): Diagonal below which to zero elements. :math:`k = 0` (the default)
1062            is the main diagonal, :math:`k < 0` is below it and :math:`k > 0` is above.
1063
1064    Returns:
1065        Upper triangle of `m`, of same shape and data-type as `m`.
1066
1067    Raises:
1068        TypeError: If input arguments have types not specified above.
1069        ValueError: If input `m`\'s rank < 1.
1070
1071    Supported Platforms:
1072        ``Ascend`` ``GPU`` ``CPU``
1073
1074    Examples:
1075        >>> import mindspore.numpy as np
1076        >>> output = np.triu(np.ones((3, 3)))
1077        >>> print(output)
1078        [[1. 1. 1.]
1079        [0. 1. 1.]
1080        [0. 0. 1.]]
1081    """
1082    if not isinstance(m, Tensor):
1083        m = asarray_const(m)
1084    dtype = m.dtype
1085    m = m.astype(mstype.float32)
1086    assist = nn_triu(m.shape, mstype.float32, k)
1087    return F.tensor_mul(assist, m).astype(dtype)
1088
1089
1090def diagonal(a, offset=0, axis1=0, axis2=1):
1091    """
1092    Returns specified diagonals.
1093
1094    If `a` is 2-D, returns the diagonal of `a` with the given offset, i.e., the
1095    collection of elements of the form ``a[i, i+offset]``. If `a` has more than two
1096    dimensions, then the axes specified by `axis1` and `axis2` are used to determine
1097    the 2-D sub-array whose diagonal is returned. The shape of the resulting
1098    array can be determined by removing `axis1` and `axis2` and appending an index
1099    to the right equal to the size of the resulting diagonals.
1100
1101    Args:
1102        a (Tensor): Array from which the diagonals are taken.
1103        offset (int, optional): Offset of the diagonal from the main diagonal.
1104            Can be positive or negative. Defaults to main diagonal.
1105        axis1 (int, optional): Axis to be used as the first axis of the 2-D
1106            sub-arrays from which the diagonals should be taken. Defaults to
1107            first axis (0).
1108        axis2 (int, optional): Axis to be used as the second axis of the 2-D
1109            sub-arrays from which the diagonals should be taken. Defaults to
1110            second axis.
1111
1112    Returns:
1113        Tensor, if `a` is 2-D, then `a` 1-D array containing the diagonal. If
1114        ``a.ndim > 2``, then the dimensions specified by `axis1` and `axis2` are removed,
1115        and a new axis inserted at the end corresponding to the diagonal.
1116
1117    Raises:
1118        ValueError: if the input tensor has less than two dimensions.
1119
1120    Supported Platforms:
1121        ``Ascend`` ``GPU`` ``CPU``
1122
1123    Examples:
1124        >>> import mindspore.numpy as np
1125        >>> a = np.arange(4).reshape(2,2).astype(np.float32)
1126        >>> print(a)
1127        [[0. 1.]
1128        [2. 3.]]
1129        >>> output = np.diagonal(a)
1130        >>> print(output)
1131        [0. 3.]
1132        >>> output = np.diagonal(a, 1)
1133        >>> print(output)
1134        [1.]
1135        >>> a = np.arange(8).reshape(2, 2, 2).astype(np.float32)
1136        >>> print(a)
1137        [[[0. 1.]
1138        [2. 3.]]
1139        [[4. 5.]
1140        [6. 7.]]]
1141        >>> output = np.diagonal(a, 0, 0, 1)
1142        >>> print(output)
1143        [[0. 6.]
1144        [1. 7.]]
1145    """
1146    return a.diagonal(offset=offset, axis1=axis1, axis2=axis2)
1147
1148
1149def trace(a, offset=0, axis1=0, axis2=1, dtype=None):
1150    """
1151    Returns the sum along diagonals of the array.
1152
1153    If `a` is 2-D, the sum along its diagonal with the given offset is returned,
1154    i.e., the sum of elements ``a[i,i+offset]`` for all `i`.
1155    If `a` has more than two dimensions, then the axes specified by `axis1` and
1156    `axis2` are used to determine the 2-D sub-arrays whose traces are returned.
1157    The shape of the resulting array is the same as that of a with `axis1` and
1158    `axis2` removed.
1159
1160    Note:
1161        On GPU, the supported dtypes are np.float16, and np.float32.
1162        On CPU, the supported dtypes are np.float16, np.float32, and np.float64.
1163
1164    Args:
1165        a (Tensor): Array from which the diagonals are taken.
1166        offset (int, optional): Offset of the diagonal from the main diagonal.
1167            Can be positive or negative. Defaults to main diagonal.
1168        axis1 (int, optional): Axis to be used as the first axis of the 2-D
1169            sub-arrays from which the diagonals should be taken. Defaults to
1170            first axis (0).
1171        axis2 (int, optional): Axis to be used as the second axis of the 2-D
1172            sub-arrays from which the diagonals should be taken. Defaults to
1173            second axis.
1174        dtype (:class:`mindspore.dtype`, optional): defaults to None. Overrides the dtype of the
1175            output Tensor.
1176
1177    Returns:
1178        Tensor, sum_along_diagonals. If `a` is 2-D, the sum along the diagonal
1179        is returned. If `a` has larger dimensions, then an array of sums along
1180        diagonals is returned.
1181
1182    Raises:
1183        ValueError: if the input tensor has less than two dimensions.
1184
1185    Supported Platforms:
1186        ``Ascend`` ``GPU`` ``CPU``
1187
1188    Examples:
1189        >>> import mindspore.numpy as np
1190        >>> output = np.trace(np.eye(3))
1191        >>> print(output)
1192        3.0
1193        >>> a = np.arange(8).reshape((2,2,2))
1194        >>> output = np.trace(a)
1195        >>> print(output)
1196        [6 8]
1197        >>> a = np.arange(24).reshape((2,2,2,3))
1198        >>> output = np.trace(a).shape
1199        >>> print(output)
1200        (2, 3)
1201    """
1202    return a.trace(offset=offset, axis1=axis1, axis2=axis2, dtype=dtype)
1203
1204
1205def _index(i, size, cartesian=True):
1206    """If cartesian=True, index 0 is swapped with index 1."""
1207    if cartesian:
1208        if i == 1:
1209            return 0
1210        if i == 0 and size >= 2:
1211            return 1
1212    return i
1213
1214
1215def meshgrid(*xi, sparse=False, indexing='xy'):
1216    """
1217    Returns coordinate matrices from coordinate vectors.
1218
1219    Make `N-D` coordinate arrays for vectorized evaluations of `N-D`
1220    scalar/vector fields over `N-D` grids, given one-dimensional
1221    coordinate arrays `x1, x2,…, xn`.
1222
1223    Note:
1224        Numpy argument copy is not supported, and a copy is always
1225        returned.
1226
1227    Args:
1228        *xi (Tensor): 1-D arrays representing the coordinates
1229            of a grid.
1230        indexing (‘xy’, ‘ij’, optional): Cartesian (‘xy’, default) or
1231            matrix (‘ij’) indexing of output. In the 2-D case with
1232            inputs of length `M` and `N`, the outputs are of shape `(N, M)`
1233            for ‘xy’ indexing and `(M, N)` for ‘ij’ indexing. In the 3-D
1234            case with inputs of length `M`, `N` and `P`, outputs are of shape
1235            `(N, M, P)` for ‘xy’ indexing and `(M, N, P)` for ‘ij’ indexing.
1236        sparse (bool, optional): If True a sparse grid is returned in
1237            order to conserve memory. Default is False.
1238
1239    Returns:
1240        Tuple of tensors, for vectors `x1, x2,…, xn` with lengths
1241        ``Ni=len(xi)``, return `(N1, N2, N3,...Nn)` shaped arrays if
1242        ``indexing=’ij’`` or `(N2, N1, N3,...Nn)` shaped arrays if
1243        ``indexing=’xy’`` with the elements of `xi` repeated to fill the matrix
1244        along the first dimension for `x1`, the second for `x2` and so on.
1245
1246    Raises:
1247        TypeError: if the input is not a tensor, or sparse is not boolean, or
1248            indexing is not 'xy' or 'ij'.
1249
1250    Supported Platforms:
1251        ``Ascend`` ``GPU`` ``CPU``
1252
1253    Examples:
1254        >>> import mindspore.numpy as np
1255        >>> x = np.linspace(0, 1, 3)
1256        >>> y = np.linspace(0, 1, 2)
1257        >>> xv, yv = np.meshgrid(x, y)
1258        >>> print(xv)
1259        [[0.  0.5 1. ]
1260        [0.  0.5 1. ]]
1261        >>> print(yv)
1262        [[0.  0.  0.]
1263        [1.  1.  1.]]
1264        >>> xv, yv = np.meshgrid(x, y, sparse=True)
1265        >>> print(xv)
1266        [[0.  0.5  1. ]]
1267        >>> print(yv)
1268        [[0.]
1269        [1.]]
1270    """
1271    _check_input_tensor(*xi)
1272    if not isinstance(sparse, bool):
1273        _raise_type_error('argument sparse should be boolean')
1274    if indexing not in ('xy', 'ij'):
1275        _raise_type_error("Valid values for `indexing` are 'xy' and 'ij'.")
1276
1277    shape_out = ()
1278    for x in xi:
1279        shape_out += (x.size,)
1280    if _is_shape_empty(shape_out):
1281        return ones(shape_out)
1282
1283    grids = []
1284    for x in xi:
1285        if F.rank(x) == 1:
1286            grids.append(x)
1287        else:
1288            grids.append(ravel(x))
1289    ndim = len(grids)
1290
1291    cartesian = indexing == 'xy'
1292    shape_out = ()
1293    for i in range(len(grids)):
1294        grid_index = _index(i, ndim, cartesian=cartesian)
1295        shape_out += (F.shape(grids[grid_index])[0],)
1296
1297    res = []
1298    for i, x in enumerate(grids):
1299        grid_index = _index(i, ndim, cartesian=cartesian)
1300        shape_expanded = _expanded_shape(ndim, shape_out[grid_index], grid_index)
1301        x = x.reshape(shape_expanded)
1302        if not sparse:
1303            x = F.tile(x, _tile_size(shape_expanded, shape_out, ndim))
1304        res.append(x)
1305    return res
1306
1307
1308class NdGrid:
1309    """
1310    Construct a multi-dimensional "meshgrid".
1311
1312    ``grid = NdGrid()`` creates an instance which will return a mesh-grid
1313    when indexed.
1314    If instantiated with an argument of ``sparse=True``, the mesh-grid is
1315    open (or not fleshed out) so that only one-dimension of each
1316    returned argument is greater than 1.
1317
1318    Args:
1319        sparse (bool): Whether the grid is sparse or not. Default is
1320            False.
1321
1322    Returns:
1323        Tensor or tuple of tensor, a meshgrid. If ``sparse=False``, returns
1324        tensors are all of the same dimensions; and if ``sparse=True``,
1325        returns tensors with only one dimension not equal to `1`.
1326    """
1327    def __init__(self, sparse=False):
1328        self.sparse = sparse
1329
1330    def __getitem__(self, keys):
1331        if isinstance(keys, slice):
1332            keys = (keys,)
1333
1334        xi = []
1335        for k in keys:
1336            if not isinstance(k.start, int) or not isinstance(k.stop, int):
1337                _raise_type_error('slice indices must be integers')
1338            if k.step:
1339                step = k.step
1340            else:
1341                step = 1
1342            if isinstance(step, complex):
1343                v = linspace(k.start, k.stop, int(abs(step)))
1344            else:
1345                v = arange(k.start, k.stop, step)
1346            xi.append(v)
1347        grids = meshgrid(*xi, sparse=self.sparse, indexing='ij')
1348
1349        if len(grids) == 1:
1350            return grids[0]
1351        if self.sparse:
1352            return grids
1353
1354        if isinstance(grids, Tensor_):
1355            return grids
1356        expanded = []
1357        for grid in grids:
1358            expanded.append(F.expand_dims(grid, 0))
1359        res = concatenate(tuple(expanded))
1360        return res
1361
1362
1363class MGridClass(NdGrid):
1364    """
1365    mgrid is an :class:`NdGrid` instance with ``sparse=False``.
1366
1367    The dimension and number of the output arrays are equal to the number
1368    of indexing dimensions. If the step length is not a complex number,
1369    then the stop is not inclusive. However, if the step length is a complex
1370    number (e.g. 5j), then the integer part of its magnitude is interpreted
1371    as specifying the number of points to create between the start and
1372    stop values, where the stop value is inclusive.
1373
1374    Note:
1375        Not supported in graph mode.
1376        Unlike Numpy, if the step length is a complex number with a real
1377        component, the step length is handled as equivalent to
1378        ``int(abs(step))``.
1379
1380    Returns:
1381        Tensor or tuple of tensor, a meshgrid.
1382
1383    Raises:
1384        TypeError: if slicing indices are not integers.
1385
1386    Supported Platforms:
1387        ``Ascend`` ``GPU`` ``CPU``
1388
1389    Examples:
1390        >>> from mindspore.numpy import mgrid
1391        >>> output = mgrid[0:5, 0:5]
1392        >>> print(output)
1393        [[[0 0 0 0 0]
1394        [1 1 1 1 1]
1395        [2 2 2 2 2]
1396        [3 3 3 3 3]
1397        [4 4 4 4 4]]
1398        [[0 1 2 3 4]
1399        [0 1 2 3 4]
1400        [0 1 2 3 4]
1401        [0 1 2 3 4]
1402        [0 1 2 3 4]]]
1403        >>> output = mgrid[-1:1:5j]
1404        >>> print(output)
1405        [-1.  -0.5  0.   0.5  1. ]
1406    """
1407    def __init__(self):
1408        super(MGridClass, self).__init__(sparse=False)
1409
1410
1411class OGridClass(NdGrid):
1412    """
1413    ogrid is an :class:`NdGrid` instance with ``sparse=True``.
1414
1415    The dimension and number of the output arrays are equal to the number
1416    of indexing dimensions. If the step length is not a complex number,
1417    then the stop is not inclusive. However, if the step length is a complex
1418    number (e.g. 5j), then the integer part of its magnitude is interpreted
1419    as specifying the number of points to create between the start and
1420    stop values, where the stop value is inclusive.
1421
1422    Note:
1423        Not supported in graph mode.
1424        Unlike Numpy, if the step length is a complex number with a real
1425        component, the step length is handled as equivalent to
1426        ``int(abs(step))``.
1427
1428    Raises:
1429        TypeError: if slicing indices are not integers.
1430
1431    Supported Platforms:
1432        ``Ascend`` ``GPU`` ``CPU``
1433
1434    Examples:
1435        >>> from mindspore.numpy import ogrid
1436        >>> output = ogrid[0:5,0:5]
1437        >>> print(output)
1438        [Tensor(shape=[5, 1], dtype=Int32, value=
1439        [[0],
1440        [1],
1441        [2]
1442        [3],
1443        [4]]), Tensor(shape=[1, 5], dtype=Int32, value=
1444        [[0, 1, 2, 3, 4]])]
1445        >>> output = ogrid[-1:1:5j]
1446        >>> print(output)
1447        [-1.  -0.5  0.   0.5  1. ]
1448    """
1449    def __init__(self):
1450        super(OGridClass, self).__init__(sparse=True)
1451
1452
1453mgrid = MGridClass()
1454
1455
1456ogrid = OGridClass()
1457
1458
1459def diag(v, k=0):
1460    """
1461    Extracts a diagonal or construct a diagonal array.
1462
1463    Args:
1464        v (Tensor): If `v` is a 2-D array, return a copy of its `k-th` diagonal.
1465            If `v` is a 1-D array, return a 2-D array with v on the `k-th` diagonal.
1466        k (int, optional): Diagonal in question. The default is 0. Use ``k>0`` for
1467            diagonals above the main diagonal, and ``k<0`` for diagonals below the
1468            main diagonal.
1469
1470    Returns:
1471        Tensor, the extracted diagonal or constructed diagonal array.
1472
1473    Raises:
1474        ValueError: if input is not 1-D or 2-D.
1475
1476    Supported Platforms:
1477        ``Ascend`` ``GPU`` ``CPU``
1478
1479    Examples:
1480        >>> import mindspore.numpy as np
1481        >>> x = np.arange(9).reshape((3,3))
1482        >>> print(x)
1483        [[0 1 2]
1484        [3 4 5]
1485        [6 7 8]]
1486        >>> output = np.diag(x)
1487        >>> print(output)
1488        [0 4 8]
1489        >>> output = np.diag(x, k=1)
1490        >>> print(output)
1491        [1 5]
1492        >>> output = np.diag(x, k=-1)
1493        >>> print(output)
1494        [3 7]
1495    """
1496    ndim = F.rank(v)
1497    if ndim == 1:
1498        return diagflat(v, k=k)
1499    if ndim == 2:
1500        shape = F.shape(v)
1501        dtype = F.dtype(v)
1502        if _is_shape_empty(shape):
1503            return _empty(dtype, (0,))
1504        e = eye(shape[0], shape[1], k, dtype)
1505        prod = F.tensor_mul(v, e)
1506
1507        cast_type = dtype
1508        if not _check_is_float(dtype):
1509            # reduce sum only supports float types
1510            cast_type = mstype.float32
1511            prod = F.cast(prod, cast_type)
1512
1513        res = F.reduce_sum(prod, 1)
1514        res = res[_max(0, -k): _min(shape[0], _max(0, shape[1] - k))]
1515
1516        if not _check_same_type(cast_type, dtype):
1517            res = F.cast(res, dtype)
1518
1519        return res
1520    return _raise_value_error("Input must be 1- or 2-d.")
1521
1522
1523def diagflat(v, k=0):
1524    """
1525    Creates a two-dimensional array with the flattened input as a diagonal.
1526
1527    Note:
1528        On GPU, the supported dtypes are np.float16, and np.float32.
1529
1530    Args:
1531        v (Tensor): Input data, which is flattened and set as the `k-th` diagonal
1532            of the output.
1533        k (int, optional): Diagonal to set; 0, the default, corresponds to the
1534            “main” diagonal, a positive (negative) `k` giving the number of the
1535            diagonal above (below) the main.
1536
1537    Returns:
1538        Tensor, The 2-D output array.
1539
1540    Raises:
1541        TypeError: if the input is not a tensor.
1542
1543    Supported Platforms:
1544        ``Ascend`` ``GPU`` ``CPU``
1545
1546    Examples:
1547        >>> import mindspore.numpy as np
1548        >>> output = np.diagflat(np.asarray([[1,2], [3,4]]))
1549        >>> print(output)
1550        [[1 0 0 0]
1551        [0 2 0 0]
1552        [0 0 3 0]
1553        [0 0 0 4]]
1554        >>> output = np.diagflat(np.asarray([1,2]), 1)
1555        >>> print(output)
1556        [[0 1 0]
1557        [0 0 2]
1558        [0 0 0]]
1559    """
1560    _check_input_tensor(v)
1561    dtype = F.dtype(v)
1562    k_abs = _abs(k)
1563    if _is_shape_empty(F.shape(v)):
1564        return zeros((k_abs, k_abs), dtype)
1565
1566    v = ravel(v)
1567    size = F.shape(v)[0]
1568    e = eye(size, size, 0, dtype)
1569    res = F.tensor_mul(v, e)
1570
1571    if k != 0:
1572        pad_y = zeros((size, k_abs), dtype)
1573        pad_x = zeros((k_abs, size + k_abs), dtype)
1574        if k < 0:
1575            res = concatenate((res, pad_y), axis=1)
1576            res = concatenate((pad_x, res), axis=0)
1577        else:
1578            res = concatenate((pad_y, res), axis=1)
1579            res = concatenate((res, pad_x), axis=0)
1580    return res
1581
1582
1583def diag_indices(n, ndim=2):
1584    """
1585    Returns the indices to access the main diagonal of an array.
1586
1587    This returns a tuple of indices that can be used to access the main
1588    diagonal of an array a with ``a.ndim >= 2`` dimensions and shape `(n, n, …, n)`.
1589    For ``a.ndim = 2`` this is the usual diagonal, for ``a.ndim > 2`` this is the set
1590    of indices to access ``a[i, i, ..., i]`` for ``i = [0..n-1]``.
1591
1592    Args:
1593        n (int): The size, along each dimension, of the arrays for which
1594            the returned indices can be used.
1595        ndim (int, optional): The number of dimensions.
1596
1597    Returns:
1598        Tuple of Tensor.
1599
1600    Raises:
1601        TypeError: if input are not integers.
1602
1603    Supported Platforms:
1604        ``Ascend`` ``GPU`` ``CPU``
1605
1606    Examples:
1607        >>> import mindspore.numpy as np
1608        >>> output = np.diag_indices(5, 3)
1609        >>> print(output)
1610        (Tensor(shape=[5], dtype=Int32, value= [0, 1, 2, 3, 4]),
1611        Tensor(shape=[5], dtype=Int32, value= [0, 1, 2, 3, 4]),
1612        Tensor(shape=[5], dtype=Int32, value= [0, 1, 2, 3, 4]))
1613    """
1614    if not isinstance(n, int) or not isinstance(ndim, int):
1615        _raise_type_error('input must be integers')
1616    return _list_comprehensions(ndim, arange(start=0, stop=n), True)
1617
1618
1619def ix_(*args):
1620    r"""
1621    Constructs an open mesh from multiple sequences.
1622
1623    This function takes `N` 1-D sequences and returns `N` outputs with `N`
1624    dimensions each, such that the shape is 1 in all but one dimension
1625    and the dimension with the non-unit shape value cycles through all
1626    N dimensions.
1627    Using ix\_ one can quickly construct index arrays that will index
1628    the cross product. ``a[np.ix_([1,3],[2,5])]`` returns the array
1629    ``[[a[1,2] a[1,5]], [a[3,2] a[3,5]]]``.
1630
1631    Note:
1632        Boolean masks are not supported.
1633
1634    Args:
1635        *args (Tensor): 1-D sequences.
1636
1637    Returns:
1638        Tuple of Tensor, `N` arrays with `N` dimensions each, with `N` the
1639        number of input sequences. Together these arrays form an open
1640        mesh.
1641
1642    Raises:
1643        TypeError: if the input is not a tensor.
1644
1645    Supported Platforms:
1646        ``Ascend`` ``GPU`` ``CPU``
1647
1648    Examples:
1649        >>> import mindspore.numpy as np
1650        >>> ixgrid = np.ix_(np.array([0, 1]), np.array([2, 4]))
1651        >>> print(ixgrid)
1652        (Tensor(shape=[2, 1], dtype=Int32, value=
1653        [[0],
1654        [1]]), Tensor(shape=[1, 2], dtype=Int32, value=
1655        [[2, 4]]))
1656    """
1657    _check_input_tensor(*args)
1658    ndim = len(args)
1659    res = ()
1660    for i, arr in enumerate(args):
1661        if F.rank(arr) != 1:
1662            return _raise_value_error('Cross index must be 1 dimensional')
1663        res += (F.reshape(arr, _expanded_shape(ndim, arr.size, i)),)
1664    return res
1665
1666
1667def vander(x, N=None, increasing=False):
1668    """
1669    Generates a Vandermonde matrix.
1670
1671    The columns of the output matrix are powers of the input vector. The order of
1672    the powers is determined by the increasing boolean argument. Specifically, when
1673    increasing is `False`, the i-th output column is the input vector raised element-wise
1674    to the power of :math:`N - i - 1`. Such a matrix with a geometric progression in each row
1675    is named for Alexandre-Theophile Vandermonde.
1676
1677    Args:
1678        x (Union[list, tuple, Tensor]): 1-D input array.
1679        N (int, optional): Number of columns in the output. If N is not specified, a
1680            square array is returned (``N = len(x)``).
1681        increasing (bool, optional): Order of the powers of the columns. If True, the
1682            powers increase from left to right, if False (the default) they are reversed.
1683
1684    Returns:
1685        Vandermonde matrix. If `increasing` is `False`, the first column is :math:`x^{(N-1)}`,
1686        the second :math:`x^{(N-2)}` and so forth. If `increasing` is `True`, the columns are
1687        :math:`x^0, x^1, ..., x^{(N-1)}`.
1688
1689    Raises:
1690        TypeError: If inputs have types not specified above.
1691        ValueError: If `x` is not 1-D, or `N` < 0.
1692
1693    Supported Platforms:
1694        ``Ascend`` ``GPU`` ``CPU``
1695
1696    Examples:
1697        >>> import mindspore.numpy as np
1698        >>> print(np.vander([1., 2., 3., 4., 5.]))
1699        [[  1.   1.   1.   1.   1.]
1700         [ 16.   8.   4.   2.   1.]
1701         [ 81.  27.   9.   3.   1.]
1702         [256.  64.  16.   4.   1.]
1703         [625. 125.  25.   5.   1.]]
1704    """
1705    if isinstance(x, (list, tuple)):
1706        x = asarray_const(x)
1707    elif not isinstance(x, Tensor):
1708        _raise_type_error("Input x must be list, tuple or Tensor, but got ", x)
1709    if x.ndim != 1:
1710        _raise_value_error("Input x must be 1-D, but got dimension=", x.ndim)
1711    N = N or x.size
1712    if not isinstance(N, int):
1713        _raise_type_error("Input N must be an integer.")
1714    if N <= 0:
1715        _raise_value_error("Input N must > 0.")
1716    if not isinstance(increasing, bool):
1717        _raise_type_error("increasing must be a bool.")
1718    exponent = _iota(x.dtype, N, increasing)
1719    x = F.expand_dims(x, 1)
1720    exponent = F.expand_dims(exponent, 0)
1721    return F.tensor_pow(x, exponent)
1722
1723
1724def indices(dimensions, dtype=mstype.int32, sparse=False):
1725    """
1726    Returns an array representing the indices of a grid.
1727
1728    Computes an array where the subarrays contain index values 0, 1, …
1729    varying only along the corresponding axis.
1730
1731    Args:
1732        dimensions (tuple or list of ints): The shape of the grid.
1733        dtype (:class:`mindspore.dtype`, optional): Data type of the result.
1734        sparse (boolean, optional): Defaults to False. Return a sparse
1735            representation of the grid instead of a dense representation.
1736
1737    Returns:
1738        Tensor or tuple of Tensor, If `sparse` is False, returns one array
1739        of grid indices, ``grid.shape = (len(dimensions),) + tuple(dimensions)``.
1740        If sparse is True, returns a tuple of arrays, with
1741        ``grid[i].shape = (1, ..., 1, dimensions[i], 1, ..., 1)`` with
1742        ``dimensions[i]`` in the `ith` place
1743
1744    Raises:
1745        TypeError: if input dimensions is not a tuple or list.
1746
1747    Supported Platforms:
1748        ``Ascend`` ``GPU`` ``CPU``
1749
1750    Examples:
1751        >>> import mindspore.numpy as np
1752        >>> grid = np.indices((2, 3))
1753        >>> print(grid)
1754        [Tensor(shape=[2, 3], dtype=Int32, value=
1755        [[0, 0, 0],
1756        [1, 1, 1]]), Tensor(shape=[2, 3], dtype=Int32, value=
1757        [[0, 1, 2],
1758        [0, 1, 2]])]
1759    """
1760    if not isinstance(dimensions, (tuple, list)):
1761        _raise_type_error('Shape of the grid must be tuple or list')
1762    grids = ()
1763    for d in dimensions:
1764        grids += (arange(d, dtype=dtype),)
1765    return meshgrid(*grids, sparse=sparse, indexing='ij')
1766
1767
1768def _check_window_size(x):
1769    """Returns True if window size is greater than 1."""
1770    if not isinstance(x, int):
1771        _raise_type_error('the number fo points should be an int')
1772    return x > 1
1773
1774
1775def bartlett(M):
1776    """
1777    Returns the Bartlett window.
1778    The Bartlett window is very similar to a triangular window, except that the
1779    end points are at zero. It is often used in signal processing for tapering a
1780    signal, without generating too much ripple in the frequency domain.
1781
1782    Args:
1783        M (int): Number of points in the output window. If zero or less, an empty
1784            array is returned.
1785
1786    Returns:
1787        Tensor, the triangular window, with the maximum value normalized to one
1788        (the value one appears only if the number of samples is odd), with the
1789        first and last samples equal to zero.
1790
1791    Raises:
1792        TypeError: if `M` is not an int.
1793
1794    Supported Platforms:
1795        ``Ascend`` ``GPU`` ``CPU``
1796
1797    Examples:
1798        >>> import mindspore.numpy as np
1799        >>> print(np.bartlett(12))
1800        [0.         0.18181819 0.36363637 0.5454545  0.72727275 0.9090909
1801        0.9090909  0.72727275 0.5454545  0.36363637 0.18181819 0.        ]
1802    """
1803    if not _check_window_size(M):
1804        return ones(_max(0, M))
1805    n = _iota(mstype.float32, M)
1806    m_minus_one = _to_tensor(M - 1)
1807    return _to_tensor(1) - F.absolute(_to_tensor(2)*n - m_minus_one)/m_minus_one
1808
1809
1810def blackman(M):
1811    """
1812    Returns the Blackman window.
1813    The Blackman window is a taper formed by using the first three terms of a
1814    summation of cosines. It was designed to have close to the minimal leakage
1815    possible. It is close to optimal, only slightly worse than a Kaiser window.
1816
1817    Args:
1818        M (int): Number of points in the output window. If zero or less, an empty
1819            array is returned.
1820
1821    Returns:
1822        Tensor, the window, with the maximum value normalized to one (the value
1823        one appears only if the number of samples is odd).
1824
1825    Raises:
1826        TypeError: if `M` is not an int.
1827
1828    Supported Platforms:
1829        ``Ascend`` ``GPU`` ``CPU``
1830
1831    Examples:
1832        >>> import mindspore.numpy as np
1833        >>> print(np.blackman(12))
1834        [-1.4901161e-08  3.2606430e-02  1.5990365e-01  4.1439798e-01
1835        7.3604518e-01  9.6704674e-01  9.6704674e-01  7.3604518e-01
1836        4.1439798e-01  1.5990365e-01  3.2606430e-02 -1.4901161e-08]
1837    """
1838    if not _check_window_size(M):
1839        return ones(_max(0, M))
1840    n_doubled = arange(1 - M, M, 2, dtype=mstype.float32)
1841    return (_to_tensor(0.42) + _to_tensor(0.5)*F.cos(_to_tensor(pi/(M - 1))*n_doubled) +
1842            _to_tensor(0.08)*F.cos(_to_tensor(2*pi/(M - 1))*n_doubled))
1843
1844
1845def hamming(M):
1846    """
1847    Returns the Hamming window.
1848    The Hamming window is a taper formed by using a weighted cosine.
1849
1850    Args:
1851        M (int): Number of points in the output window. If zero or less, an empty
1852            array is returned.
1853
1854    Returns:
1855        Tensor, the window, with the maximum value normalized to one (the value
1856        one appears only if the number of samples is odd).
1857
1858    Raises:
1859        TypeError: if `M` is not an int.
1860
1861    Supported Platforms:
1862        ``Ascend`` ``GPU`` ``CPU``
1863
1864    Examples:
1865        >>> import mindspore.numpy as np
1866        >>> print(np.hamming(12))
1867        [0.08000001 0.15302339 0.34890914 0.6054648  0.841236   0.9813669
1868        0.9813668  0.8412359  0.6054647  0.34890908 0.15302327 0.08000001]
1869    """
1870    if not _check_window_size(M):
1871        return ones(_max(0, M))
1872    n = _iota(mstype.float32, M)
1873    return _to_tensor(0.54) - _to_tensor(0.46)*F.cos(_to_tensor(2*pi/(M - 1))*n)
1874
1875
1876def hanning(M):
1877    """
1878    Returns the Hanning window.
1879    The Hanning window is a taper formed by using a weighted cosine.
1880
1881    Args:
1882        M (int): Number of points in the output window. If zero or less, an empty
1883            array is returned.
1884
1885    Returns:
1886        Tensor, the window, with the maximum value normalized to one (the value
1887        one appears only if the number of samples is odd).
1888
1889    Raises:
1890        TypeError: if `M` is not an int.
1891
1892    Supported Platforms:
1893        ``Ascend`` ``GPU`` ``CPU``
1894
1895    Examples:
1896        >>> import mindspore.numpy as np
1897        >>> print(np.hanning(12))
1898        [0.         0.07937324 0.29229254 0.5711574  0.8274304  0.9797465
1899        0.97974646 0.82743025 0.5711573  0.29229245 0.07937312 0.        ]
1900    """
1901    if not _check_window_size(M):
1902        return ones(_max(0, M))
1903    n = _iota(mstype.float32, M)
1904    return _to_tensor(0.5) - _to_tensor(0.5)*F.cos(_to_tensor(2*pi/(M - 1))*n)
1905
1906
1907@constexpr
1908def tri_indices(n, k=0, m=None, upper=True):
1909    """Returns triu/tril indices in o(nm) time."""
1910    if not isinstance(n, (int, float, bool)):
1911        raise TypeError("Input n must be a number.")
1912    if not isinstance(k, (int, float, bool)):
1913        raise TypeError("Input k must be a number.")
1914    if m is None:
1915        m = n
1916    elif not isinstance(m, (int, float, bool)):
1917        raise TypeError("Input m must be a number.")
1918    if upper:
1919        compare = operator.ge
1920    else:
1921        compare = operator.le
1922    x_coordinate = []
1923    y_coordinate = []
1924    # math.ceil is used to match numpy's behaviour
1925    for i in range(math.ceil(n)):
1926        curr_limit = i + k
1927        for j in range(math.ceil(m)):
1928            if compare(j, curr_limit):
1929                x_coordinate.append(i)
1930                y_coordinate.append(j)
1931    return asarray_const(x_coordinate), asarray_const(y_coordinate)
1932
1933
1934def triu_indices(n, k=0, m=None):
1935    """
1936    Returns the indices for the upper-triangle of an (n, m) array.
1937
1938    Args:
1939        n (int): The size of the arrays for which the returned indices will be valid.
1940        k (int, optional): Diagonal offset, default is 0.
1941        m (int, optional): The column dimension of the arrays for which the returned
1942            arrays will be valid. By default `m` is taken equal to `n`.
1943
1944    Returns:
1945        The indices for the triangle. The returned tuple contains two tensors, each
1946        with the indices along one dimension of the tensor.
1947
1948    Raises:
1949        TypeError: if `n`, `k`, `m` are not numbers.
1950
1951    Supported Platforms:
1952        ``Ascend`` ``GPU`` ``CPU``
1953
1954    Examples:
1955        >>> import mindspore.numpy as np
1956        >>> print(np.triu_indices(3))
1957        (Tensor(shape=[6], dtype=Int32, value= [0, 0, 0, 1, 1, 2]),
1958         Tensor(shape=[6], dtype=Int32, value= [0, 1, 2, 1, 2, 2]))
1959    """
1960    return tri_indices(n, k, m, True)
1961
1962
1963def tril_indices(n, k=0, m=None):
1964    """
1965    Returns the indices for the lower-triangle of an (n, m) array.
1966
1967    Args:
1968        n (int): The size of the arrays for which the returned indices will be valid.
1969        k (int, optional): Diagonal offset, default is 0.
1970        m (int, optional): The column dimension of the arrays for which the returned
1971            arrays will be valid. By default `m` is taken equal to `n`.
1972
1973    Returns:
1974        The indices for the triangle. The returned tuple contains two tensors, each
1975        with the indices along one dimension of the tensor.
1976
1977    Raises:
1978        TypeError: if `n`, `k`, `m` are not numbers.
1979
1980    Supported Platforms:
1981        ``Ascend`` ``GPU`` ``CPU``
1982
1983    Examples:
1984        >>> import mindspore.numpy as np
1985        >>> print(np.tril_indices(3))
1986        (Tensor(shape=[6], dtype=Int32, value= [0, 1, 1, 2, 2, 2]),
1987        Tensor(shape=[6], dtype=Int32, value= [0, 0, 1, 0, 1, 2]))
1988    """
1989    return tri_indices(n, k, m, False)
1990
1991
1992def triu_indices_from(arr, k=0):
1993    """
1994    Returns the indices for the upper-triangle of `arr`.
1995
1996    Args:
1997        arr (Union[Tensor, list, tuple]): 2-dimensional array.
1998        k (int, optional): Diagonal offset, default is 0.
1999
2000    Returns:
2001        triu_indices_from, tuple of 2 tensor, shape(N)
2002        Indices for the upper-triangle of `arr`.
2003
2004    Raises:
2005        TypeError: if `arr` cannot be converted to tensor, or `k` is not a number.
2006        ValueError: if `arr` cannot be converted to a 2-dimensional tensor.
2007
2008    Supported Platforms:
2009        ``Ascend`` ``GPU`` ``CPU``
2010
2011    Examples:
2012        >>> import mindspore.numpy as np
2013        >>> tensor = np.ones((3,3))
2014        >>> print(np.triu_indices_from(tensor))
2015        (Tensor(shape=[6], dtype=Int32, value= [0, 0, 0, 1, 1, 2]),
2016        Tensor(shape=[6], dtype=Int32, value= [0, 1, 2, 1, 2, 2]))
2017    """
2018    arr = asarray(arr)
2019    if arr.ndim != 2:
2020        _raise_value_error("input array must be 2-d")
2021    return triu_indices(arr.shape[-2], k=k, m=arr.shape[-1])
2022
2023
2024def tril_indices_from(arr, k=0):
2025    """
2026    Returns the indices for the lower-triangle of `arr`.
2027
2028    Args:
2029        arr (Union[Tensor, list, tuple]): 2-dimensional array.
2030        k (int, optional): Diagonal offset, default is 0.
2031
2032    Returns:
2033        triu_indices_from, tuple of 2 tensor, shape(N)
2034        Indices for the upper-triangle of `arr`.
2035
2036    Raises:
2037        TypeError: if `arr` cannot be converted to tensor, or `k` is not a number.
2038        ValueError: if `arr` cannot be converted to a 2-dimensional tensor.
2039
2040    Supported Platforms:
2041        ``Ascend`` ``GPU`` ``CPU``
2042
2043    Examples:
2044        >>> import mindspore.numpy as np
2045        >>> tensor = np.ones((3,3))
2046        >>> print(np.tril_indices_from(tensor))
2047        (Tensor(shape=[6], dtype=Int32, value= [0, 1, 1, 2, 2, 2]),
2048         Tensor(shape=[6], dtype=Int32, value= [0, 0, 1, 0, 1, 2]))
2049    """
2050    arr = asarray(arr)
2051    if arr.ndim != 2:
2052        _raise_value_error("input array must be 2-d")
2053    return tril_indices(arr.shape[-2], k=k, m=arr.shape[-1])
2054
2055
2056def histogram_bin_edges(a, bins=10, range=None, weights=None): # pylint: disable=redefined-builtin
2057    """
2058    Function to calculate only the edges of the bins used by the histogram function.
2059
2060    Note:
2061        String values for `bins` is not supported.
2062
2063    Args:
2064        a (Union[int, float, bool, list, tuple, Tensor]): Input data. The histogram
2065            is computed over the flattened array.
2066        bins ((Union[int, tuple, list, Tensor])): If `bins` is an int, it defines the number
2067            of equal-width bins in the given range (10, by default). If `bins` is a
2068            sequence, it defines the bin edges, including the rightmost edge,
2069            allowing for non-uniform bin widths.
2070        range((float, float), optional): The lower and upper range of the bins. If
2071            not provided, `range` is simply ``(a.min(), a.max())``. Values outside
2072            the range are ignored. The first element of the range must be less than
2073            or equal to the second. Default is None.
2074        weights(Union[int, float, bool, list, tuple, Tensor], optional):  An array of weights,
2075            of the same shape as `a`. Each value in `a` only contributes its associated weight
2076            towards the bin count (instead of 1). This is currently not used by any of the bin
2077            estimators, but may be in the future. Default is None.
2078
2079    Returns:
2080        Tensor, the edges to pass into `histogram`.
2081
2082    Supported Platforms:
2083        ``Ascend`` ``GPU`` ``CPU``
2084
2085    Raises:
2086        TypeError: if `bins` is an array and not one-dimensional.
2087
2088    Examples:
2089        >>> import mindspore.numpy as np
2090        >>> arr = np.array([0, 0, 0, 1, 2, 3, 3, 4, 5])
2091        >>> print(np.histogram_bin_edges(arr, bins=2))
2092        [0.  2.5 5. ]
2093    """
2094    a = _to_tensor(a)
2095    if weights is not None:
2096        weights = _to_tensor(weights)
2097        if F.shape(a) != F.shape(weights):
2098            _raise_value_error('weights should have the same shape as a')
2099    if isinstance(bins, (tuple, list, Tensor)):
2100        bins = _to_tensor(bins)
2101        if F.rank(bins) != 1:
2102            _raise_value_error('`bins` must be 1d, when an array')
2103        return bins
2104    if isinstance(bins, str):
2105        # linspace does not support Tensor for num
2106        _raise_unimplemented_error('string value for `bins` not implemented')
2107    a = a.ravel().astype(mstype.float32)
2108    if range is None:
2109        start = F.reduce_min(a)
2110        end = F.reduce_max(a)
2111    else:
2112        if not isinstance(range, (list, tuple)) or len(range) != 2:
2113            _raise_value_error('`range` should take the form (start, end)')
2114        start, end = range
2115        if start > end:
2116            _raise_value_error('max must be larger than min in range parameter')
2117        start, end = _to_tensor(start, end)
2118    no_range = (end - start) == 0
2119    start = where(no_range, start - 0.5, start)
2120    end = where(no_range, end + 0.5, end)
2121    return linspace(start, end, bins + 1)
2122
2123
2124def _pad_empty(arr, pad_width):
2125    """
2126    pads the array with constant values, used in mode: "empty"
2127    """
2128    dtype = arr.dtype
2129    for i in range(arr.ndim):
2130        shape = arr.shape
2131        pad_before = ()
2132        pad_after = ()
2133        # To avoid any memory issues, we don't make tensor with 0s in their shapes
2134        if pad_width[i][0] > 0:
2135            pad_before += (empty(_tuple_setitem(shape, i, pad_width[i][0]), dtype=dtype),)
2136        if pad_width[i][1] > 0:
2137            pad_after += (empty(_tuple_setitem(shape, i, pad_width[i][1]), dtype=dtype),)
2138        tensor_with_pad = pad_before + (arr,) + pad_after
2139        arr = concatenate(tensor_with_pad, axis=i)
2140    return arr
2141
2142
2143def _pad_constant(arr, pad_width, value):
2144    """
2145    pads the array with constant values, used in mode: "constant"
2146    """
2147    dtype = arr.dtype
2148    for i in range(arr.ndim):
2149        shape = arr.shape
2150        pad_before = ()
2151        pad_after = ()
2152        # To avoid any memory issues, we don't make tensor with 0s in their shapes
2153        if pad_width[i][0] > 0:
2154            pad_before += (full(_tuple_setitem(shape, i, pad_width[i][0]), value[i][0], dtype=dtype),)
2155        if pad_width[i][1] > 0:
2156            pad_after += (full(_tuple_setitem(shape, i, pad_width[i][1]), value[i][1], dtype=dtype),)
2157        tensor_with_pad = pad_before + (arr,) + pad_after
2158        arr = concatenate(tensor_with_pad, axis=i)
2159    return arr
2160
2161
2162def _pad_statistic(arr, pad_width, stat_length, stat_op):
2163    """
2164    pads the array with values calculated along the given axis, used in mode: "maximum",
2165    "minimum", "mean"
2166    """
2167    ndim = arr.ndim
2168    shape = arr.shape
2169    if stat_length is None:
2170        stat_length = _make_stat_length(shape)
2171    else:
2172        stat_length = _convert_pad_to_nd(stat_length, ndim)
2173    stat_length = _limit_stat_length(stat_length, shape)
2174    for i in range(ndim):
2175        pad_before = stat_op(_slice_along_axis(arr, i, 0, stat_length[i][0]), i)
2176        pad_before = (F.tile(pad_before, _tuple_setitem((1,)*ndim, i, pad_width[i][0])),)
2177        pad_after = stat_op(_slice_along_axis(arr, i, shape[i]-stat_length[i][1], shape[i]), i)
2178        pad_after = (F.tile(pad_after, _tuple_setitem((1,)*ndim, i, pad_width[i][1])),)
2179        tensor_with_pad = pad_before + (arr,) + pad_after
2180        arr = concatenate(tensor_with_pad, axis=i)
2181    return arr
2182
2183
2184def _pad_edge(arr, pad_width):
2185    """pad_edge is equivalent to pad_statistic with stat_lenght=1, used in mode:"edge"."""
2186    def identity_op(arr, axis):
2187        return arr
2188    return _pad_statistic(arr, pad_width, 1, identity_op)
2189
2190
2191def _pad_wrap(arr, pad_width):
2192    """The behaviour of wrap mode is consistent with jax.numpy, used in mode:"wrap"."""
2193    ndim = arr.ndim
2194    shape = arr.shape
2195    for i in range(ndim):
2196        padsize_before = pad_width[i][0] % shape[i]
2197        padsize_after = pad_width[i][1] % shape[i]
2198        total_repeats = pad_width[i][0] // shape[i] + 1 + pad_width[i][1] // shape[i]
2199        tensor_with_pad = ()
2200        # To avoid any memory issues, we don't make tensor with 0s in their shapes
2201        if padsize_before > 0:
2202            tensor_with_pad += (_slice_along_axis(arr, i, shape[i]-padsize_before, shape[i]),)
2203        tensor_with_pad += (F.tile(arr, _tuple_setitem((1,)*ndim, i, total_repeats)),)
2204        if padsize_after > 0:
2205            tensor_with_pad += (_slice_along_axis(arr, i, 0, padsize_after),)
2206        arr = concatenate(tensor_with_pad, axis=i)
2207    return arr
2208
2209
2210def _pad_linear(arr, pad_width, end_values):
2211    """Pads the arr with linear range values, used in mode: "linear_ramp"."""
2212    ndim = arr.ndim
2213    shape = arr.shape
2214    dtype = arr.dtype
2215    end_values = _convert_pad_to_nd(end_values, ndim)
2216    for i in range(ndim):
2217        left_value = _slice_along_axis(arr, i, 0, 1)
2218        right_value = _slice_along_axis(arr, i, shape[i]-1, shape[i])
2219        pad_before = ()
2220        pad_after = ()
2221        if pad_width[i][0] > 0:
2222            pad_before = (linspace(end_values[i][0], left_value, num=pad_width[i][0],
2223                                   endpoint=False, dtype=dtype, axis=i).squeeze(i+1),)
2224        if pad_width[i][1] > 0:
2225            pad_after = linspace(right_value, end_values[i][1], num=pad_width[i][1]+1,
2226                                 endpoint=True, dtype=dtype, axis=i).squeeze(i+1)
2227            pad_after = (_slice_along_axis(pad_after, i, 1, pad_width[i][1]+1),)
2228        tensor_with_pad = pad_before + (arr,) + pad_after
2229        arr = concatenate(tensor_with_pad, axis=i)
2230    return arr
2231
2232
2233def _add_pads_before(arr, pad_args, mode):
2234    """handle pads before the array"""
2235    idx, array_length, times_to_pad_before, additional_pad_before, reflect_type = pad_args
2236    curr_pad = None
2237    endpoint_adder = None
2238    edge_before = _slice_along_axis(arr, idx, 0, 1)
2239    if mode == "reflect":
2240        endpoint_adder = 1
2241    else:
2242        endpoint_adder = 0
2243    # Deal with paddings before the original array
2244    for times in range(times_to_pad_before):
2245        if times < times_to_pad_before - 1:
2246            endpoint = array_length
2247        else:
2248            endpoint = additional_pad_before + endpoint_adder
2249        if endpoint != endpoint_adder:
2250            curr_pad = _slice_along_axis(arr, idx, endpoint_adder, endpoint)
2251            curr_pad = flip(curr_pad, axis=idx)
2252            if reflect_type == "odd":
2253                curr_pad = 2 * edge_before - curr_pad
2254            arr = P.Concat(idx)((curr_pad, arr))
2255            edge_before = _slice_along_axis(arr, idx, 0, 1)
2256    return arr
2257
2258
2259def _add_pads_after(arr, pad_args, mode):
2260    """handle pads after the array"""
2261    idx, array_length, times_to_pad_after, additional_pad_after, reflect_type = pad_args
2262    curr_pad = None
2263    endpoint_adder = None
2264    edge_end = _slice_along_axis(arr, idx, arr.shape[idx]-1, arr.shape[idx])
2265    if mode == "reflect":
2266        endpoint_adder = 1
2267    else:
2268        endpoint_adder = 0
2269    # Deal with paddings after the original array
2270    for times in range(times_to_pad_after):
2271        if times < times_to_pad_after - 1:
2272            startpoint = arr.shape[idx] - array_length
2273        else:
2274            startpoint = arr.shape[idx] - additional_pad_after - endpoint_adder
2275        if startpoint != arr.shape[idx] - endpoint_adder:
2276            curr_pad = _slice_along_axis(arr, idx, startpoint, arr.shape[idx] - endpoint_adder)
2277            curr_pad = flip(curr_pad, axis=idx)
2278            if reflect_type == "odd":
2279                curr_pad = 2 * edge_end - curr_pad
2280            arr = P.Concat(idx)((arr, curr_pad))
2281            edge_end = _slice_along_axis(arr, idx, arr.shape[idx]-1, arr.shape[idx])
2282    return arr
2283
2284
2285def _pad_symmetric(arr, pad_width, reflect_type):
2286    """pad the array with symmetric paddings"""
2287    for i in range(arr.ndim):
2288        array_length = arr.shape[i]
2289
2290        has_pad_before = (pad_width[i][0] > 0)
2291        has_pad_after = (pad_width[i][1] > 0)
2292
2293        times_to_pad_before = pad_width[i][0] // array_length + 1
2294        additional_pad_before = pad_width[i][0] % array_length
2295        times_to_pad_after = pad_width[i][1] // array_length + 1
2296        additional_pad_after = pad_width[i][1] % array_length
2297        if has_pad_before:
2298            # Deal with paddings before the original array
2299            pad_args = (i, array_length, times_to_pad_before, additional_pad_before, reflect_type)
2300            arr = _add_pads_before(arr, pad_args, "symmetric")
2301        if has_pad_after:
2302            # Deal with paddings after the original array
2303            pad_args = (i, array_length, times_to_pad_after, additional_pad_after, reflect_type)
2304            arr = _add_pads_after(arr, pad_args, "symmetric")
2305    return arr
2306
2307
2308def _pad_reflect(arr, pad_width, reflect_type):
2309    """
2310    pad the array with reflect paddings, this is very similar to symmetric paddings,
2311    but differs at how edges are selected.
2312    """
2313    for i in range(arr.ndim):
2314        array_length = arr.shape[i]
2315        if array_length == 1:
2316            total_repeats = pad_width[i][0] + pad_width[i][1] + 1
2317            arr = F.tile(arr, _tuple_setitem((1,)*arr.ndim, i, total_repeats))
2318        else:
2319            has_pad_before = (pad_width[i][0] > 0)
2320            has_pad_after = (pad_width[i][1] > 0)
2321
2322            pad_size = array_length - 1
2323            times_to_pad_before = pad_width[i][0] // pad_size + 1
2324            additional_pad_before = pad_width[i][0] % pad_size
2325            times_to_pad_after = pad_width[i][1] // pad_size + 1
2326            additional_pad_after = pad_width[i][1] % pad_size
2327            if has_pad_before:
2328                # Deal with paddings before the original array
2329                pad_args = (i, array_length, times_to_pad_before, additional_pad_before, reflect_type)
2330                arr = _add_pads_before(arr, pad_args, "reflect")
2331            if has_pad_after:
2332                # Deal with paddings after the original array
2333                pad_args = (i, array_length, times_to_pad_after, additional_pad_after, reflect_type)
2334                arr = _add_pads_after(arr, pad_args, "reflect")
2335    return arr
2336
2337
2338def _pad_func(arr, pad_width, func, **kwargs):
2339    """applies padding function over different axis."""
2340    # first creates a padded array with fixed length.
2341    arr_dim = arr.ndim
2342    pad_width = _convert_pad_to_nd(pad_width, arr_dim)
2343    arr = _pad_empty(arr, pad_width)
2344    for i in range(arr_dim):
2345        # function signature: padding_func(tensor, iaxis_pad_width, iaxis, kwargs)
2346        arr = apply_along_axis(func, i, arr, pad_width[i], i, kwargs)
2347    return arr
2348
2349
2350@constexpr
2351def _make_stat_length(shape):
2352    """converts the stat_length values."""
2353    return tuple((shape[i], shape[i]) for i, _ in enumerate(shape))
2354
2355
2356@constexpr
2357def _limit_stat_length(stat_length, shape):
2358    """limits the stat_length to current array length along given dimension."""
2359    return tuple((min(stat_pair[0], shape[i]), min(stat_pair[1], shape[i])) for i, stat_pair in enumerate(stat_length))
2360
2361
2362@constexpr
2363def _convert_pad_to_nd(pad_values, ndim):
2364    """broadcasts the pad_values to (ndim * 2)"""
2365    if not isinstance(pad_values, (int, list, tuple, Tensor)):
2366        raise TypeError(
2367            "pad_width, stat_length, constant_values or end_values should only be int, list, tuple or tensor")
2368    pad_tensor = _to_tensor(pad_values)
2369    pad_shape = pad_tensor.shape
2370    if not pad_shape:
2371        pad_values = tuple((((pad_values,) * 2) for i in range(ndim)))
2372    elif pad_shape == (1,):
2373        pad_values = tuple((tuple(pad_values) * 2) for i in range(ndim))
2374    elif pad_shape == (2,):
2375        pad_values = tuple(tuple(pad_values) for i in range(ndim))
2376    elif pad_shape == (1, 2):
2377        pad_values = tuple(tuple(pad_values[0]) for i in range(ndim))
2378    elif pad_shape == (ndim, 2):
2379        pad_values = tuple(tuple(pad_pair) for pad_pair in pad_values)
2380    else:
2381        raise ValueError(f"input values must be able to broadcast to {(ndim, 2)}")
2382    return pad_values
2383
2384
2385def pad(arr, pad_width, mode="constant", stat_length=None, constant_values=0,
2386        end_values=0, reflect_type="even", **kwargs):
2387    """
2388    Pads an array.
2389
2390    Note:
2391        Currently, `median` mode is not supported. `reflect` and `symmetric` mode
2392        only supports GPU backend.
2393
2394    Args:
2395        arr (Union[list, tuple, Tensor]): The array to pad.
2396        pad_width (Union[int, tuple, list]): Number of values padded to the edges of
2397            each axis. :class:`((before_1, after_1), ... (before_N, after_N))` creates
2398            unique pad widths for each axis. :class:`((before, after),)` yields same
2399            before and after pad for each axis. :class:`(pad,)` or int is a shortcut
2400            for :class:`before = after = pad width` for all axes.
2401        mode (string, optional):
2402            One of the following string values:
2403
2404            - constant (default): Pads with a constant value.
2405            - edge: Pads with the edge values of `arr`.
2406            - linear_ramp: Pads with the linear ramp between end_value and the `arr` edge value.
2407            - maximum: Pads with the maximum value of all or part of the vector along each axis.
2408            - mean: Pads with the mean value of all or part of the vector along each axis.
2409            - median: Pads with the median value of all or part of the vector along each axis.
2410            - minimum: Pads with the minimum value of all or part of the vector along each axis.
2411            - reflect: Pads with the reflection of the vector mirrored on the first
2412              and last values of the vector along each axis.
2413            - symmetric: Pads with the reflection of the vector mirrored along the edge
2414              of the `arr`.
2415            - wrap: Pads with the wrap of the vector along the axis. The first values
2416              are used to pad the end and the end values are used to pad the beginning.
2417            - empty: Pads with undefined values.
2418            - <function>: The padding function, if used, should modify and return a new 1-d tensor.
2419              It has the following signature: :class:`padding_func(tensor, iaxis_pad_width, iaxis, kwargs)`
2420        stat_length (Union[tuple, list, int], optional): Used in \'maximum\', \'mean\',
2421            \'median\', and \'minimum\'.  Number of values at edge of each axis used
2422            to calculate the statistic value. :class:`((before_1, after_1), ... (before_N, after_N))`
2423            creates unique statistic lengths for each axis. :class:`((before, after),)`
2424            yields same before and after statistic lengths for each axis. :class:`(stat_length,)`
2425            or int is a shortcut for :class:`before = after = statistic length` for all
2426            axes. Default is :class:`None`, to use the entire axis.
2427        constant_values (Union[tuple, list, int], optional):
2428            Used in :class:`constant mode`. The values to set the padded values for each
2429            axis. :class:`((before_1, after_1), ... (before_N, after_N))` creates unique pad
2430            constants for each axis. :class:`((before, after),)` yields same before and
2431            after constants for each axis. :class:`(constant,)` or :class:`constant` is
2432            a shortcut for :class:`before = after = constant` for all axes. Default is 0.
2433        end_values (Union[tuple, list, int], optional): Used in 'linear_ramp'.  The values
2434            used for the ending value of the linear_ramp and that will form the edge of
2435            the padded `arr`. :class:`((before_1, after_1), ... (before_N, after_N))`
2436            unique end values for each axis. :class:`((before, after),)` yields same before
2437            and after end values for each axis. :class:`(constant,)` or :class:`constant`
2438            is a shortcut for :class:`before = after = constant` for all axes. Default is 0.
2439        reflect_type(string, optional) can choose between \'even\' and \'odd\'. Used in
2440            \'reflect\', and \'symmetric\'. The \'even\' style is the default with an
2441            unaltered reflection around the edge value. For the \'odd\' style, the extended
2442            part of the `arr` is created by subtracting the reflected values from two times
2443            the edge value.
2444
2445    Returns:
2446        Padded tensor of rank equal to `arr` with shape increased according to `pad_width`.
2447
2448    Raises:
2449        TypeError: if `arr`, `pad_width`, `stat_length`, `constant_values` or `end_values`
2450            have types not specified above.
2451        ValueError: if `mode` cannot be recognized, or if `pad_width`, `stat_length`,
2452            `constant_values`, `end_values` cannot broadcast to :class:`(arr.ndim, 2)`,
2453            or if keyword arguments got unexpected inputs.
2454        NotImplementedError: if mode is function or '/median'/.
2455
2456    Supported Platforms:
2457        ``Ascend`` ``GPU`` ``CPU``
2458
2459    Examples:
2460        >>> import mindspore.numpy as np
2461        >>> tensor = np.array([1., 2., 3., 4., 5.])
2462        >>> print(np.pad(tensor, (3, 4)))
2463        [0. 0. 0. 1. 2. 3. 4. 5. 0. 0. 0. 0.]
2464        >>> print(np.pad(tensor, (3, 4), mode="wrap"))
2465        [3. 4. 5. 1. 2. 3. 4. 5. 1. 2. 3. 4.]
2466        >>> print(np.pad(tensor, (3, 4), mode="linear_ramp", end_values=(10, 10)))
2467        [10.    7.    4.    1.    2.    3.    4.    5.    6.25  7.5   8.75 10.  ]
2468    """
2469    arr = _to_tensor(arr)
2470    if arr.ndim == 0:
2471        return arr
2472    pad_width = _convert_pad_to_nd(pad_width, arr.ndim)
2473    stat_func = {"maximum": _reduce_max_keepdims,
2474                 "minimum": _reduce_min_keepdims,
2475                 "mean": _reduce_mean_keepdims,
2476                 "median": "not implemented"}
2477
2478    if mode not in ("constant", "maximum", "minimum", "mean", "median", "edge",
2479                    "wrap", "linear_ramp", "symmetric", "reflect", "empty") and \
2480                    not _callable(arr, mode):
2481        _raise_value_error("Input mode not supported.")
2482
2483    if mode == "constant":
2484        constant_values = _convert_pad_to_nd(constant_values, arr.ndim)
2485        return _pad_constant(arr, pad_width, constant_values)
2486    if mode in ("maximum", "minimum", "mean", "median"):
2487        # support median mode once P.Sort/P.Median is supported on GPU/CPU
2488        if mode == "median":
2489            _raise_unimplemented_error("median mode is not supported yet")
2490        return _pad_statistic(arr, pad_width, stat_length, stat_func[mode])
2491    if mode == "edge":
2492        return _pad_edge(arr, pad_width)
2493    if mode == "wrap":
2494        return _pad_wrap(arr, pad_width)
2495    if mode == "linear_ramp":
2496        return _pad_linear(arr, pad_width, end_values)
2497    if mode == "symmetric":
2498        return _pad_symmetric(arr, pad_width, reflect_type)
2499    if mode == "reflect":
2500        return _pad_reflect(arr, pad_width, reflect_type)
2501    if mode == 'empty':
2502        return _pad_empty(arr, pad_width)
2503    return _pad_func(arr, pad_width, mode, **kwargs)
2504