2531 lines
75 KiB
Python
2531 lines
75 KiB
Python
|
import functools
|
||
|
import itertools
|
||
|
import operator
|
||
|
import sys
|
||
|
import warnings
|
||
|
import numbers
|
||
|
import builtins
|
||
|
|
||
|
import numpy as np
|
||
|
from . import multiarray
|
||
|
from .multiarray import (
|
||
|
fastCopyAndTranspose, ALLOW_THREADS,
|
||
|
BUFSIZE, CLIP, MAXDIMS, MAY_SHARE_BOUNDS, MAY_SHARE_EXACT, RAISE,
|
||
|
WRAP, arange, array, asarray, asanyarray, ascontiguousarray,
|
||
|
asfortranarray, broadcast, can_cast, compare_chararrays,
|
||
|
concatenate, copyto, dot, dtype, empty,
|
||
|
empty_like, flatiter, frombuffer, from_dlpack, fromfile, fromiter,
|
||
|
fromstring, inner, lexsort, matmul, may_share_memory,
|
||
|
min_scalar_type, ndarray, nditer, nested_iters, promote_types,
|
||
|
putmask, result_type, set_numeric_ops, shares_memory, vdot, where,
|
||
|
zeros, normalize_axis_index, _get_promotion_state, _set_promotion_state,
|
||
|
_using_numpy2_behavior)
|
||
|
|
||
|
from . import overrides
|
||
|
from . import umath
|
||
|
from . import shape_base
|
||
|
from .overrides import set_array_function_like_doc, set_module
|
||
|
from .umath import (multiply, invert, sin, PINF, NAN)
|
||
|
from . import numerictypes
|
||
|
from .numerictypes import longlong, intc, int_, float_, complex_, bool_
|
||
|
from ..exceptions import ComplexWarning, TooHardError, AxisError
|
||
|
from ._ufunc_config import errstate, _no_nep50_warning
|
||
|
|
||
|
bitwise_not = invert
|
||
|
ufunc = type(sin)
|
||
|
newaxis = None
|
||
|
|
||
|
array_function_dispatch = functools.partial(
|
||
|
overrides.array_function_dispatch, module='numpy')
|
||
|
|
||
|
|
||
|
__all__ = [
|
||
|
'newaxis', 'ndarray', 'flatiter', 'nditer', 'nested_iters', 'ufunc',
|
||
|
'arange', 'array', 'asarray', 'asanyarray', 'ascontiguousarray',
|
||
|
'asfortranarray', 'zeros', 'count_nonzero', 'empty', 'broadcast', 'dtype',
|
||
|
'fromstring', 'fromfile', 'frombuffer', 'from_dlpack', 'where',
|
||
|
'argwhere', 'copyto', 'concatenate', 'fastCopyAndTranspose', 'lexsort',
|
||
|
'set_numeric_ops', 'can_cast', 'promote_types', 'min_scalar_type',
|
||
|
'result_type', 'isfortran', 'empty_like', 'zeros_like', 'ones_like',
|
||
|
'correlate', 'convolve', 'inner', 'dot', 'outer', 'vdot', 'roll',
|
||
|
'rollaxis', 'moveaxis', 'cross', 'tensordot', 'little_endian',
|
||
|
'fromiter', 'array_equal', 'array_equiv', 'indices', 'fromfunction',
|
||
|
'isclose', 'isscalar', 'binary_repr', 'base_repr', 'ones',
|
||
|
'identity', 'allclose', 'compare_chararrays', 'putmask',
|
||
|
'flatnonzero', 'Inf', 'inf', 'infty', 'Infinity', 'nan', 'NaN',
|
||
|
'False_', 'True_', 'bitwise_not', 'CLIP', 'RAISE', 'WRAP', 'MAXDIMS',
|
||
|
'BUFSIZE', 'ALLOW_THREADS', 'full', 'full_like',
|
||
|
'matmul', 'shares_memory', 'may_share_memory', 'MAY_SHARE_BOUNDS',
|
||
|
'MAY_SHARE_EXACT', '_get_promotion_state', '_set_promotion_state',
|
||
|
'_using_numpy2_behavior']
|
||
|
|
||
|
|
||
|
def _zeros_like_dispatcher(a, dtype=None, order=None, subok=None, shape=None):
|
||
|
return (a,)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_zeros_like_dispatcher)
|
||
|
def zeros_like(a, dtype=None, order='K', subok=True, shape=None):
|
||
|
"""
|
||
|
Return an array of zeros with the same shape and type as a given array.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : array_like
|
||
|
The shape and data-type of `a` define these same attributes of
|
||
|
the returned array.
|
||
|
dtype : data-type, optional
|
||
|
Overrides the data type of the result.
|
||
|
|
||
|
.. versionadded:: 1.6.0
|
||
|
order : {'C', 'F', 'A', or 'K'}, optional
|
||
|
Overrides the memory layout of the result. 'C' means C-order,
|
||
|
'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous,
|
||
|
'C' otherwise. 'K' means match the layout of `a` as closely
|
||
|
as possible.
|
||
|
|
||
|
.. versionadded:: 1.6.0
|
||
|
subok : bool, optional.
|
||
|
If True, then the newly created array will use the sub-class
|
||
|
type of `a`, otherwise it will be a base-class array. Defaults
|
||
|
to True.
|
||
|
shape : int or sequence of ints, optional.
|
||
|
Overrides the shape of the result. If order='K' and the number of
|
||
|
dimensions is unchanged, will try to keep order, otherwise,
|
||
|
order='C' is implied.
|
||
|
|
||
|
.. versionadded:: 1.17.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
out : ndarray
|
||
|
Array of zeros with the same shape and type as `a`.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
empty_like : Return an empty array with shape and type of input.
|
||
|
ones_like : Return an array of ones with shape and type of input.
|
||
|
full_like : Return a new array with shape of input filled with value.
|
||
|
zeros : Return a new array setting values to zero.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> x = np.arange(6)
|
||
|
>>> x = x.reshape((2, 3))
|
||
|
>>> x
|
||
|
array([[0, 1, 2],
|
||
|
[3, 4, 5]])
|
||
|
>>> np.zeros_like(x)
|
||
|
array([[0, 0, 0],
|
||
|
[0, 0, 0]])
|
||
|
|
||
|
>>> y = np.arange(3, dtype=float)
|
||
|
>>> y
|
||
|
array([0., 1., 2.])
|
||
|
>>> np.zeros_like(y)
|
||
|
array([0., 0., 0.])
|
||
|
|
||
|
"""
|
||
|
res = empty_like(a, dtype=dtype, order=order, subok=subok, shape=shape)
|
||
|
# needed instead of a 0 to get same result as zeros for string dtypes
|
||
|
z = zeros(1, dtype=res.dtype)
|
||
|
multiarray.copyto(res, z, casting='unsafe')
|
||
|
return res
|
||
|
|
||
|
|
||
|
@set_array_function_like_doc
|
||
|
@set_module('numpy')
|
||
|
def ones(shape, dtype=None, order='C', *, like=None):
|
||
|
"""
|
||
|
Return a new array of given shape and type, filled with ones.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
shape : int or sequence of ints
|
||
|
Shape of the new array, e.g., ``(2, 3)`` or ``2``.
|
||
|
dtype : data-type, optional
|
||
|
The desired data-type for the array, e.g., `numpy.int8`. Default is
|
||
|
`numpy.float64`.
|
||
|
order : {'C', 'F'}, optional, default: C
|
||
|
Whether to store multi-dimensional data in row-major
|
||
|
(C-style) or column-major (Fortran-style) order in
|
||
|
memory.
|
||
|
${ARRAY_FUNCTION_LIKE}
|
||
|
|
||
|
.. versionadded:: 1.20.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
out : ndarray
|
||
|
Array of ones with the given shape, dtype, and order.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
ones_like : Return an array of ones with shape and type of input.
|
||
|
empty : Return a new uninitialized array.
|
||
|
zeros : Return a new array setting values to zero.
|
||
|
full : Return a new array of given shape filled with value.
|
||
|
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.ones(5)
|
||
|
array([1., 1., 1., 1., 1.])
|
||
|
|
||
|
>>> np.ones((5,), dtype=int)
|
||
|
array([1, 1, 1, 1, 1])
|
||
|
|
||
|
>>> np.ones((2, 1))
|
||
|
array([[1.],
|
||
|
[1.]])
|
||
|
|
||
|
>>> s = (2,2)
|
||
|
>>> np.ones(s)
|
||
|
array([[1., 1.],
|
||
|
[1., 1.]])
|
||
|
|
||
|
"""
|
||
|
if like is not None:
|
||
|
return _ones_with_like(like, shape, dtype=dtype, order=order)
|
||
|
|
||
|
a = empty(shape, dtype, order)
|
||
|
multiarray.copyto(a, 1, casting='unsafe')
|
||
|
return a
|
||
|
|
||
|
|
||
|
_ones_with_like = array_function_dispatch()(ones)
|
||
|
|
||
|
|
||
|
def _ones_like_dispatcher(a, dtype=None, order=None, subok=None, shape=None):
|
||
|
return (a,)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_ones_like_dispatcher)
|
||
|
def ones_like(a, dtype=None, order='K', subok=True, shape=None):
|
||
|
"""
|
||
|
Return an array of ones with the same shape and type as a given array.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : array_like
|
||
|
The shape and data-type of `a` define these same attributes of
|
||
|
the returned array.
|
||
|
dtype : data-type, optional
|
||
|
Overrides the data type of the result.
|
||
|
|
||
|
.. versionadded:: 1.6.0
|
||
|
order : {'C', 'F', 'A', or 'K'}, optional
|
||
|
Overrides the memory layout of the result. 'C' means C-order,
|
||
|
'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous,
|
||
|
'C' otherwise. 'K' means match the layout of `a` as closely
|
||
|
as possible.
|
||
|
|
||
|
.. versionadded:: 1.6.0
|
||
|
subok : bool, optional.
|
||
|
If True, then the newly created array will use the sub-class
|
||
|
type of `a`, otherwise it will be a base-class array. Defaults
|
||
|
to True.
|
||
|
shape : int or sequence of ints, optional.
|
||
|
Overrides the shape of the result. If order='K' and the number of
|
||
|
dimensions is unchanged, will try to keep order, otherwise,
|
||
|
order='C' is implied.
|
||
|
|
||
|
.. versionadded:: 1.17.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
out : ndarray
|
||
|
Array of ones with the same shape and type as `a`.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
empty_like : Return an empty array with shape and type of input.
|
||
|
zeros_like : Return an array of zeros with shape and type of input.
|
||
|
full_like : Return a new array with shape of input filled with value.
|
||
|
ones : Return a new array setting values to one.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> x = np.arange(6)
|
||
|
>>> x = x.reshape((2, 3))
|
||
|
>>> x
|
||
|
array([[0, 1, 2],
|
||
|
[3, 4, 5]])
|
||
|
>>> np.ones_like(x)
|
||
|
array([[1, 1, 1],
|
||
|
[1, 1, 1]])
|
||
|
|
||
|
>>> y = np.arange(3, dtype=float)
|
||
|
>>> y
|
||
|
array([0., 1., 2.])
|
||
|
>>> np.ones_like(y)
|
||
|
array([1., 1., 1.])
|
||
|
|
||
|
"""
|
||
|
res = empty_like(a, dtype=dtype, order=order, subok=subok, shape=shape)
|
||
|
multiarray.copyto(res, 1, casting='unsafe')
|
||
|
return res
|
||
|
|
||
|
|
||
|
def _full_dispatcher(shape, fill_value, dtype=None, order=None, *, like=None):
|
||
|
return(like,)
|
||
|
|
||
|
|
||
|
@set_array_function_like_doc
|
||
|
@set_module('numpy')
|
||
|
def full(shape, fill_value, dtype=None, order='C', *, like=None):
|
||
|
"""
|
||
|
Return a new array of given shape and type, filled with `fill_value`.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
shape : int or sequence of ints
|
||
|
Shape of the new array, e.g., ``(2, 3)`` or ``2``.
|
||
|
fill_value : scalar or array_like
|
||
|
Fill value.
|
||
|
dtype : data-type, optional
|
||
|
The desired data-type for the array The default, None, means
|
||
|
``np.array(fill_value).dtype``.
|
||
|
order : {'C', 'F'}, optional
|
||
|
Whether to store multidimensional data in C- or Fortran-contiguous
|
||
|
(row- or column-wise) order in memory.
|
||
|
${ARRAY_FUNCTION_LIKE}
|
||
|
|
||
|
.. versionadded:: 1.20.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
out : ndarray
|
||
|
Array of `fill_value` with the given shape, dtype, and order.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
full_like : Return a new array with shape of input filled with value.
|
||
|
empty : Return a new uninitialized array.
|
||
|
ones : Return a new array setting values to one.
|
||
|
zeros : Return a new array setting values to zero.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.full((2, 2), np.inf)
|
||
|
array([[inf, inf],
|
||
|
[inf, inf]])
|
||
|
>>> np.full((2, 2), 10)
|
||
|
array([[10, 10],
|
||
|
[10, 10]])
|
||
|
|
||
|
>>> np.full((2, 2), [1, 2])
|
||
|
array([[1, 2],
|
||
|
[1, 2]])
|
||
|
|
||
|
"""
|
||
|
if like is not None:
|
||
|
return _full_with_like(
|
||
|
like, shape, fill_value, dtype=dtype, order=order)
|
||
|
|
||
|
if dtype is None:
|
||
|
fill_value = asarray(fill_value)
|
||
|
dtype = fill_value.dtype
|
||
|
a = empty(shape, dtype, order)
|
||
|
multiarray.copyto(a, fill_value, casting='unsafe')
|
||
|
return a
|
||
|
|
||
|
|
||
|
_full_with_like = array_function_dispatch()(full)
|
||
|
|
||
|
|
||
|
def _full_like_dispatcher(a, fill_value, dtype=None, order=None, subok=None, shape=None):
|
||
|
return (a,)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_full_like_dispatcher)
|
||
|
def full_like(a, fill_value, dtype=None, order='K', subok=True, shape=None):
|
||
|
"""
|
||
|
Return a full array with the same shape and type as a given array.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : array_like
|
||
|
The shape and data-type of `a` define these same attributes of
|
||
|
the returned array.
|
||
|
fill_value : array_like
|
||
|
Fill value.
|
||
|
dtype : data-type, optional
|
||
|
Overrides the data type of the result.
|
||
|
order : {'C', 'F', 'A', or 'K'}, optional
|
||
|
Overrides the memory layout of the result. 'C' means C-order,
|
||
|
'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous,
|
||
|
'C' otherwise. 'K' means match the layout of `a` as closely
|
||
|
as possible.
|
||
|
subok : bool, optional.
|
||
|
If True, then the newly created array will use the sub-class
|
||
|
type of `a`, otherwise it will be a base-class array. Defaults
|
||
|
to True.
|
||
|
shape : int or sequence of ints, optional.
|
||
|
Overrides the shape of the result. If order='K' and the number of
|
||
|
dimensions is unchanged, will try to keep order, otherwise,
|
||
|
order='C' is implied.
|
||
|
|
||
|
.. versionadded:: 1.17.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
out : ndarray
|
||
|
Array of `fill_value` with the same shape and type as `a`.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
empty_like : Return an empty array with shape and type of input.
|
||
|
ones_like : Return an array of ones with shape and type of input.
|
||
|
zeros_like : Return an array of zeros with shape and type of input.
|
||
|
full : Return a new array of given shape filled with value.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> x = np.arange(6, dtype=int)
|
||
|
>>> np.full_like(x, 1)
|
||
|
array([1, 1, 1, 1, 1, 1])
|
||
|
>>> np.full_like(x, 0.1)
|
||
|
array([0, 0, 0, 0, 0, 0])
|
||
|
>>> np.full_like(x, 0.1, dtype=np.double)
|
||
|
array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1])
|
||
|
>>> np.full_like(x, np.nan, dtype=np.double)
|
||
|
array([nan, nan, nan, nan, nan, nan])
|
||
|
|
||
|
>>> y = np.arange(6, dtype=np.double)
|
||
|
>>> np.full_like(y, 0.1)
|
||
|
array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1])
|
||
|
|
||
|
>>> y = np.zeros([2, 2, 3], dtype=int)
|
||
|
>>> np.full_like(y, [0, 0, 255])
|
||
|
array([[[ 0, 0, 255],
|
||
|
[ 0, 0, 255]],
|
||
|
[[ 0, 0, 255],
|
||
|
[ 0, 0, 255]]])
|
||
|
"""
|
||
|
res = empty_like(a, dtype=dtype, order=order, subok=subok, shape=shape)
|
||
|
multiarray.copyto(res, fill_value, casting='unsafe')
|
||
|
return res
|
||
|
|
||
|
|
||
|
def _count_nonzero_dispatcher(a, axis=None, *, keepdims=None):
|
||
|
return (a,)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_count_nonzero_dispatcher)
|
||
|
def count_nonzero(a, axis=None, *, keepdims=False):
|
||
|
"""
|
||
|
Counts the number of non-zero values in the array ``a``.
|
||
|
|
||
|
The word "non-zero" is in reference to the Python 2.x
|
||
|
built-in method ``__nonzero__()`` (renamed ``__bool__()``
|
||
|
in Python 3.x) of Python objects that tests an object's
|
||
|
"truthfulness". For example, any number is considered
|
||
|
truthful if it is nonzero, whereas any string is considered
|
||
|
truthful if it is not the empty string. Thus, this function
|
||
|
(recursively) counts how many elements in ``a`` (and in
|
||
|
sub-arrays thereof) have their ``__nonzero__()`` or ``__bool__()``
|
||
|
method evaluated to ``True``.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : array_like
|
||
|
The array for which to count non-zeros.
|
||
|
axis : int or tuple, optional
|
||
|
Axis or tuple of axes along which to count non-zeros.
|
||
|
Default is None, meaning that non-zeros will be counted
|
||
|
along a flattened version of ``a``.
|
||
|
|
||
|
.. versionadded:: 1.12.0
|
||
|
|
||
|
keepdims : bool, optional
|
||
|
If this is set to True, the axes that are counted are left
|
||
|
in the result as dimensions with size one. With this option,
|
||
|
the result will broadcast correctly against the input array.
|
||
|
|
||
|
.. versionadded:: 1.19.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
count : int or array of int
|
||
|
Number of non-zero values in the array along a given axis.
|
||
|
Otherwise, the total number of non-zero values in the array
|
||
|
is returned.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
nonzero : Return the coordinates of all the non-zero values.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.count_nonzero(np.eye(4))
|
||
|
4
|
||
|
>>> a = np.array([[0, 1, 7, 0],
|
||
|
... [3, 0, 2, 19]])
|
||
|
>>> np.count_nonzero(a)
|
||
|
5
|
||
|
>>> np.count_nonzero(a, axis=0)
|
||
|
array([1, 1, 2, 1])
|
||
|
>>> np.count_nonzero(a, axis=1)
|
||
|
array([2, 3])
|
||
|
>>> np.count_nonzero(a, axis=1, keepdims=True)
|
||
|
array([[2],
|
||
|
[3]])
|
||
|
"""
|
||
|
if axis is None and not keepdims:
|
||
|
return multiarray.count_nonzero(a)
|
||
|
|
||
|
a = asanyarray(a)
|
||
|
|
||
|
# TODO: this works around .astype(bool) not working properly (gh-9847)
|
||
|
if np.issubdtype(a.dtype, np.character):
|
||
|
a_bool = a != a.dtype.type()
|
||
|
else:
|
||
|
a_bool = a.astype(np.bool_, copy=False)
|
||
|
|
||
|
return a_bool.sum(axis=axis, dtype=np.intp, keepdims=keepdims)
|
||
|
|
||
|
|
||
|
@set_module('numpy')
|
||
|
def isfortran(a):
|
||
|
"""
|
||
|
Check if the array is Fortran contiguous but *not* C contiguous.
|
||
|
|
||
|
This function is obsolete and, because of changes due to relaxed stride
|
||
|
checking, its return value for the same array may differ for versions
|
||
|
of NumPy >= 1.10.0 and previous versions. If you only want to check if an
|
||
|
array is Fortran contiguous use ``a.flags.f_contiguous`` instead.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : ndarray
|
||
|
Input array.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
isfortran : bool
|
||
|
Returns True if the array is Fortran contiguous but *not* C contiguous.
|
||
|
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
|
||
|
np.array allows to specify whether the array is written in C-contiguous
|
||
|
order (last index varies the fastest), or FORTRAN-contiguous order in
|
||
|
memory (first index varies the fastest).
|
||
|
|
||
|
>>> a = np.array([[1, 2, 3], [4, 5, 6]], order='C')
|
||
|
>>> a
|
||
|
array([[1, 2, 3],
|
||
|
[4, 5, 6]])
|
||
|
>>> np.isfortran(a)
|
||
|
False
|
||
|
|
||
|
>>> b = np.array([[1, 2, 3], [4, 5, 6]], order='F')
|
||
|
>>> b
|
||
|
array([[1, 2, 3],
|
||
|
[4, 5, 6]])
|
||
|
>>> np.isfortran(b)
|
||
|
True
|
||
|
|
||
|
|
||
|
The transpose of a C-ordered array is a FORTRAN-ordered array.
|
||
|
|
||
|
>>> a = np.array([[1, 2, 3], [4, 5, 6]], order='C')
|
||
|
>>> a
|
||
|
array([[1, 2, 3],
|
||
|
[4, 5, 6]])
|
||
|
>>> np.isfortran(a)
|
||
|
False
|
||
|
>>> b = a.T
|
||
|
>>> b
|
||
|
array([[1, 4],
|
||
|
[2, 5],
|
||
|
[3, 6]])
|
||
|
>>> np.isfortran(b)
|
||
|
True
|
||
|
|
||
|
C-ordered arrays evaluate as False even if they are also FORTRAN-ordered.
|
||
|
|
||
|
>>> np.isfortran(np.array([1, 2], order='F'))
|
||
|
False
|
||
|
|
||
|
"""
|
||
|
return a.flags.fnc
|
||
|
|
||
|
|
||
|
def _argwhere_dispatcher(a):
|
||
|
return (a,)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_argwhere_dispatcher)
|
||
|
def argwhere(a):
|
||
|
"""
|
||
|
Find the indices of array elements that are non-zero, grouped by element.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : array_like
|
||
|
Input data.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
index_array : (N, a.ndim) ndarray
|
||
|
Indices of elements that are non-zero. Indices are grouped by element.
|
||
|
This array will have shape ``(N, a.ndim)`` where ``N`` is the number of
|
||
|
non-zero items.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
where, nonzero
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
``np.argwhere(a)`` is almost the same as ``np.transpose(np.nonzero(a))``,
|
||
|
but produces a result of the correct shape for a 0D array.
|
||
|
|
||
|
The output of ``argwhere`` is not suitable for indexing arrays.
|
||
|
For this purpose use ``nonzero(a)`` instead.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> x = np.arange(6).reshape(2,3)
|
||
|
>>> x
|
||
|
array([[0, 1, 2],
|
||
|
[3, 4, 5]])
|
||
|
>>> np.argwhere(x>1)
|
||
|
array([[0, 2],
|
||
|
[1, 0],
|
||
|
[1, 1],
|
||
|
[1, 2]])
|
||
|
|
||
|
"""
|
||
|
# nonzero does not behave well on 0d, so promote to 1d
|
||
|
if np.ndim(a) == 0:
|
||
|
a = shape_base.atleast_1d(a)
|
||
|
# then remove the added dimension
|
||
|
return argwhere(a)[:,:0]
|
||
|
return transpose(nonzero(a))
|
||
|
|
||
|
|
||
|
def _flatnonzero_dispatcher(a):
|
||
|
return (a,)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_flatnonzero_dispatcher)
|
||
|
def flatnonzero(a):
|
||
|
"""
|
||
|
Return indices that are non-zero in the flattened version of a.
|
||
|
|
||
|
This is equivalent to ``np.nonzero(np.ravel(a))[0]``.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : array_like
|
||
|
Input data.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
res : ndarray
|
||
|
Output array, containing the indices of the elements of ``a.ravel()``
|
||
|
that are non-zero.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
nonzero : Return the indices of the non-zero elements of the input array.
|
||
|
ravel : Return a 1-D array containing the elements of the input array.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> x = np.arange(-2, 3)
|
||
|
>>> x
|
||
|
array([-2, -1, 0, 1, 2])
|
||
|
>>> np.flatnonzero(x)
|
||
|
array([0, 1, 3, 4])
|
||
|
|
||
|
Use the indices of the non-zero elements as an index array to extract
|
||
|
these elements:
|
||
|
|
||
|
>>> x.ravel()[np.flatnonzero(x)]
|
||
|
array([-2, -1, 1, 2])
|
||
|
|
||
|
"""
|
||
|
return np.nonzero(np.ravel(a))[0]
|
||
|
|
||
|
|
||
|
def _correlate_dispatcher(a, v, mode=None):
|
||
|
return (a, v)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_correlate_dispatcher)
|
||
|
def correlate(a, v, mode='valid'):
|
||
|
r"""
|
||
|
Cross-correlation of two 1-dimensional sequences.
|
||
|
|
||
|
This function computes the correlation as generally defined in signal
|
||
|
processing texts:
|
||
|
|
||
|
.. math:: c_k = \sum_n a_{n+k} \cdot \overline{v}_n
|
||
|
|
||
|
with a and v sequences being zero-padded where necessary and
|
||
|
:math:`\overline x` denoting complex conjugation.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a, v : array_like
|
||
|
Input sequences.
|
||
|
mode : {'valid', 'same', 'full'}, optional
|
||
|
Refer to the `convolve` docstring. Note that the default
|
||
|
is 'valid', unlike `convolve`, which uses 'full'.
|
||
|
old_behavior : bool
|
||
|
`old_behavior` was removed in NumPy 1.10. If you need the old
|
||
|
behavior, use `multiarray.correlate`.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
out : ndarray
|
||
|
Discrete cross-correlation of `a` and `v`.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
convolve : Discrete, linear convolution of two one-dimensional sequences.
|
||
|
multiarray.correlate : Old, no conjugate, version of correlate.
|
||
|
scipy.signal.correlate : uses FFT which has superior performance on large arrays.
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
The definition of correlation above is not unique and sometimes correlation
|
||
|
may be defined differently. Another common definition is:
|
||
|
|
||
|
.. math:: c'_k = \sum_n a_{n} \cdot \overline{v_{n+k}}
|
||
|
|
||
|
which is related to :math:`c_k` by :math:`c'_k = c_{-k}`.
|
||
|
|
||
|
`numpy.correlate` may perform slowly in large arrays (i.e. n = 1e5) because it does
|
||
|
not use the FFT to compute the convolution; in that case, `scipy.signal.correlate` might
|
||
|
be preferable.
|
||
|
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.correlate([1, 2, 3], [0, 1, 0.5])
|
||
|
array([3.5])
|
||
|
>>> np.correlate([1, 2, 3], [0, 1, 0.5], "same")
|
||
|
array([2. , 3.5, 3. ])
|
||
|
>>> np.correlate([1, 2, 3], [0, 1, 0.5], "full")
|
||
|
array([0.5, 2. , 3.5, 3. , 0. ])
|
||
|
|
||
|
Using complex sequences:
|
||
|
|
||
|
>>> np.correlate([1+1j, 2, 3-1j], [0, 1, 0.5j], 'full')
|
||
|
array([ 0.5-0.5j, 1.0+0.j , 1.5-1.5j, 3.0-1.j , 0.0+0.j ])
|
||
|
|
||
|
Note that you get the time reversed, complex conjugated result
|
||
|
(:math:`\overline{c_{-k}}`) when the two input sequences a and v change
|
||
|
places:
|
||
|
|
||
|
>>> np.correlate([0, 1, 0.5j], [1+1j, 2, 3-1j], 'full')
|
||
|
array([ 0.0+0.j , 3.0+1.j , 1.5+1.5j, 1.0+0.j , 0.5+0.5j])
|
||
|
|
||
|
"""
|
||
|
return multiarray.correlate2(a, v, mode)
|
||
|
|
||
|
|
||
|
def _convolve_dispatcher(a, v, mode=None):
|
||
|
return (a, v)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_convolve_dispatcher)
|
||
|
def convolve(a, v, mode='full'):
|
||
|
"""
|
||
|
Returns the discrete, linear convolution of two one-dimensional sequences.
|
||
|
|
||
|
The convolution operator is often seen in signal processing, where it
|
||
|
models the effect of a linear time-invariant system on a signal [1]_. In
|
||
|
probability theory, the sum of two independent random variables is
|
||
|
distributed according to the convolution of their individual
|
||
|
distributions.
|
||
|
|
||
|
If `v` is longer than `a`, the arrays are swapped before computation.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : (N,) array_like
|
||
|
First one-dimensional input array.
|
||
|
v : (M,) array_like
|
||
|
Second one-dimensional input array.
|
||
|
mode : {'full', 'valid', 'same'}, optional
|
||
|
'full':
|
||
|
By default, mode is 'full'. This returns the convolution
|
||
|
at each point of overlap, with an output shape of (N+M-1,). At
|
||
|
the end-points of the convolution, the signals do not overlap
|
||
|
completely, and boundary effects may be seen.
|
||
|
|
||
|
'same':
|
||
|
Mode 'same' returns output of length ``max(M, N)``. Boundary
|
||
|
effects are still visible.
|
||
|
|
||
|
'valid':
|
||
|
Mode 'valid' returns output of length
|
||
|
``max(M, N) - min(M, N) + 1``. The convolution product is only given
|
||
|
for points where the signals overlap completely. Values outside
|
||
|
the signal boundary have no effect.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
out : ndarray
|
||
|
Discrete, linear convolution of `a` and `v`.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
scipy.signal.fftconvolve : Convolve two arrays using the Fast Fourier
|
||
|
Transform.
|
||
|
scipy.linalg.toeplitz : Used to construct the convolution operator.
|
||
|
polymul : Polynomial multiplication. Same output as convolve, but also
|
||
|
accepts poly1d objects as input.
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
The discrete convolution operation is defined as
|
||
|
|
||
|
.. math:: (a * v)_n = \\sum_{m = -\\infty}^{\\infty} a_m v_{n - m}
|
||
|
|
||
|
It can be shown that a convolution :math:`x(t) * y(t)` in time/space
|
||
|
is equivalent to the multiplication :math:`X(f) Y(f)` in the Fourier
|
||
|
domain, after appropriate padding (padding is necessary to prevent
|
||
|
circular convolution). Since multiplication is more efficient (faster)
|
||
|
than convolution, the function `scipy.signal.fftconvolve` exploits the
|
||
|
FFT to calculate the convolution of large data-sets.
|
||
|
|
||
|
References
|
||
|
----------
|
||
|
.. [1] Wikipedia, "Convolution",
|
||
|
https://en.wikipedia.org/wiki/Convolution
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
Note how the convolution operator flips the second array
|
||
|
before "sliding" the two across one another:
|
||
|
|
||
|
>>> np.convolve([1, 2, 3], [0, 1, 0.5])
|
||
|
array([0. , 1. , 2.5, 4. , 1.5])
|
||
|
|
||
|
Only return the middle values of the convolution.
|
||
|
Contains boundary effects, where zeros are taken
|
||
|
into account:
|
||
|
|
||
|
>>> np.convolve([1,2,3],[0,1,0.5], 'same')
|
||
|
array([1. , 2.5, 4. ])
|
||
|
|
||
|
The two arrays are of the same length, so there
|
||
|
is only one position where they completely overlap:
|
||
|
|
||
|
>>> np.convolve([1,2,3],[0,1,0.5], 'valid')
|
||
|
array([2.5])
|
||
|
|
||
|
"""
|
||
|
a, v = array(a, copy=False, ndmin=1), array(v, copy=False, ndmin=1)
|
||
|
if (len(v) > len(a)):
|
||
|
a, v = v, a
|
||
|
if len(a) == 0:
|
||
|
raise ValueError('a cannot be empty')
|
||
|
if len(v) == 0:
|
||
|
raise ValueError('v cannot be empty')
|
||
|
return multiarray.correlate(a, v[::-1], mode)
|
||
|
|
||
|
|
||
|
def _outer_dispatcher(a, b, out=None):
|
||
|
return (a, b, out)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_outer_dispatcher)
|
||
|
def outer(a, b, out=None):
|
||
|
"""
|
||
|
Compute the outer product of two vectors.
|
||
|
|
||
|
Given two vectors `a` and `b` of length ``M`` and ``N``, repsectively,
|
||
|
the outer product [1]_ is::
|
||
|
|
||
|
[[a_0*b_0 a_0*b_1 ... a_0*b_{N-1} ]
|
||
|
[a_1*b_0 .
|
||
|
[ ... .
|
||
|
[a_{M-1}*b_0 a_{M-1}*b_{N-1} ]]
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : (M,) array_like
|
||
|
First input vector. Input is flattened if
|
||
|
not already 1-dimensional.
|
||
|
b : (N,) array_like
|
||
|
Second input vector. Input is flattened if
|
||
|
not already 1-dimensional.
|
||
|
out : (M, N) ndarray, optional
|
||
|
A location where the result is stored
|
||
|
|
||
|
.. versionadded:: 1.9.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
out : (M, N) ndarray
|
||
|
``out[i, j] = a[i] * b[j]``
|
||
|
|
||
|
See also
|
||
|
--------
|
||
|
inner
|
||
|
einsum : ``einsum('i,j->ij', a.ravel(), b.ravel())`` is the equivalent.
|
||
|
ufunc.outer : A generalization to dimensions other than 1D and other
|
||
|
operations. ``np.multiply.outer(a.ravel(), b.ravel())``
|
||
|
is the equivalent.
|
||
|
tensordot : ``np.tensordot(a.ravel(), b.ravel(), axes=((), ()))``
|
||
|
is the equivalent.
|
||
|
|
||
|
References
|
||
|
----------
|
||
|
.. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*, 3rd
|
||
|
ed., Baltimore, MD, Johns Hopkins University Press, 1996,
|
||
|
pg. 8.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
Make a (*very* coarse) grid for computing a Mandelbrot set:
|
||
|
|
||
|
>>> rl = np.outer(np.ones((5,)), np.linspace(-2, 2, 5))
|
||
|
>>> rl
|
||
|
array([[-2., -1., 0., 1., 2.],
|
||
|
[-2., -1., 0., 1., 2.],
|
||
|
[-2., -1., 0., 1., 2.],
|
||
|
[-2., -1., 0., 1., 2.],
|
||
|
[-2., -1., 0., 1., 2.]])
|
||
|
>>> im = np.outer(1j*np.linspace(2, -2, 5), np.ones((5,)))
|
||
|
>>> im
|
||
|
array([[0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j],
|
||
|
[0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j],
|
||
|
[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
|
||
|
[0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j],
|
||
|
[0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j]])
|
||
|
>>> grid = rl + im
|
||
|
>>> grid
|
||
|
array([[-2.+2.j, -1.+2.j, 0.+2.j, 1.+2.j, 2.+2.j],
|
||
|
[-2.+1.j, -1.+1.j, 0.+1.j, 1.+1.j, 2.+1.j],
|
||
|
[-2.+0.j, -1.+0.j, 0.+0.j, 1.+0.j, 2.+0.j],
|
||
|
[-2.-1.j, -1.-1.j, 0.-1.j, 1.-1.j, 2.-1.j],
|
||
|
[-2.-2.j, -1.-2.j, 0.-2.j, 1.-2.j, 2.-2.j]])
|
||
|
|
||
|
An example using a "vector" of letters:
|
||
|
|
||
|
>>> x = np.array(['a', 'b', 'c'], dtype=object)
|
||
|
>>> np.outer(x, [1, 2, 3])
|
||
|
array([['a', 'aa', 'aaa'],
|
||
|
['b', 'bb', 'bbb'],
|
||
|
['c', 'cc', 'ccc']], dtype=object)
|
||
|
|
||
|
"""
|
||
|
a = asarray(a)
|
||
|
b = asarray(b)
|
||
|
return multiply(a.ravel()[:, newaxis], b.ravel()[newaxis, :], out)
|
||
|
|
||
|
|
||
|
def _tensordot_dispatcher(a, b, axes=None):
|
||
|
return (a, b)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_tensordot_dispatcher)
|
||
|
def tensordot(a, b, axes=2):
|
||
|
"""
|
||
|
Compute tensor dot product along specified axes.
|
||
|
|
||
|
Given two tensors, `a` and `b`, and an array_like object containing
|
||
|
two array_like objects, ``(a_axes, b_axes)``, sum the products of
|
||
|
`a`'s and `b`'s elements (components) over the axes specified by
|
||
|
``a_axes`` and ``b_axes``. The third argument can be a single non-negative
|
||
|
integer_like scalar, ``N``; if it is such, then the last ``N`` dimensions
|
||
|
of `a` and the first ``N`` dimensions of `b` are summed over.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a, b : array_like
|
||
|
Tensors to "dot".
|
||
|
|
||
|
axes : int or (2,) array_like
|
||
|
* integer_like
|
||
|
If an int N, sum over the last N axes of `a` and the first N axes
|
||
|
of `b` in order. The sizes of the corresponding axes must match.
|
||
|
* (2,) array_like
|
||
|
Or, a list of axes to be summed over, first sequence applying to `a`,
|
||
|
second to `b`. Both elements array_like must be of the same length.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
output : ndarray
|
||
|
The tensor dot product of the input.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
dot, einsum
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
Three common use cases are:
|
||
|
* ``axes = 0`` : tensor product :math:`a\\otimes b`
|
||
|
* ``axes = 1`` : tensor dot product :math:`a\\cdot b`
|
||
|
* ``axes = 2`` : (default) tensor double contraction :math:`a:b`
|
||
|
|
||
|
When `axes` is integer_like, the sequence for evaluation will be: first
|
||
|
the -Nth axis in `a` and 0th axis in `b`, and the -1th axis in `a` and
|
||
|
Nth axis in `b` last.
|
||
|
|
||
|
When there is more than one axis to sum over - and they are not the last
|
||
|
(first) axes of `a` (`b`) - the argument `axes` should consist of
|
||
|
two sequences of the same length, with the first axis to sum over given
|
||
|
first in both sequences, the second axis second, and so forth.
|
||
|
|
||
|
The shape of the result consists of the non-contracted axes of the
|
||
|
first tensor, followed by the non-contracted axes of the second.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
A "traditional" example:
|
||
|
|
||
|
>>> a = np.arange(60.).reshape(3,4,5)
|
||
|
>>> b = np.arange(24.).reshape(4,3,2)
|
||
|
>>> c = np.tensordot(a,b, axes=([1,0],[0,1]))
|
||
|
>>> c.shape
|
||
|
(5, 2)
|
||
|
>>> c
|
||
|
array([[4400., 4730.],
|
||
|
[4532., 4874.],
|
||
|
[4664., 5018.],
|
||
|
[4796., 5162.],
|
||
|
[4928., 5306.]])
|
||
|
>>> # A slower but equivalent way of computing the same...
|
||
|
>>> d = np.zeros((5,2))
|
||
|
>>> for i in range(5):
|
||
|
... for j in range(2):
|
||
|
... for k in range(3):
|
||
|
... for n in range(4):
|
||
|
... d[i,j] += a[k,n,i] * b[n,k,j]
|
||
|
>>> c == d
|
||
|
array([[ True, True],
|
||
|
[ True, True],
|
||
|
[ True, True],
|
||
|
[ True, True],
|
||
|
[ True, True]])
|
||
|
|
||
|
An extended example taking advantage of the overloading of + and \\*:
|
||
|
|
||
|
>>> a = np.array(range(1, 9))
|
||
|
>>> a.shape = (2, 2, 2)
|
||
|
>>> A = np.array(('a', 'b', 'c', 'd'), dtype=object)
|
||
|
>>> A.shape = (2, 2)
|
||
|
>>> a; A
|
||
|
array([[[1, 2],
|
||
|
[3, 4]],
|
||
|
[[5, 6],
|
||
|
[7, 8]]])
|
||
|
array([['a', 'b'],
|
||
|
['c', 'd']], dtype=object)
|
||
|
|
||
|
>>> np.tensordot(a, A) # third argument default is 2 for double-contraction
|
||
|
array(['abbcccdddd', 'aaaaabbbbbbcccccccdddddddd'], dtype=object)
|
||
|
|
||
|
>>> np.tensordot(a, A, 1)
|
||
|
array([[['acc', 'bdd'],
|
||
|
['aaacccc', 'bbbdddd']],
|
||
|
[['aaaaacccccc', 'bbbbbdddddd'],
|
||
|
['aaaaaaacccccccc', 'bbbbbbbdddddddd']]], dtype=object)
|
||
|
|
||
|
>>> np.tensordot(a, A, 0) # tensor product (result too long to incl.)
|
||
|
array([[[[['a', 'b'],
|
||
|
['c', 'd']],
|
||
|
...
|
||
|
|
||
|
>>> np.tensordot(a, A, (0, 1))
|
||
|
array([[['abbbbb', 'cddddd'],
|
||
|
['aabbbbbb', 'ccdddddd']],
|
||
|
[['aaabbbbbbb', 'cccddddddd'],
|
||
|
['aaaabbbbbbbb', 'ccccdddddddd']]], dtype=object)
|
||
|
|
||
|
>>> np.tensordot(a, A, (2, 1))
|
||
|
array([[['abb', 'cdd'],
|
||
|
['aaabbbb', 'cccdddd']],
|
||
|
[['aaaaabbbbbb', 'cccccdddddd'],
|
||
|
['aaaaaaabbbbbbbb', 'cccccccdddddddd']]], dtype=object)
|
||
|
|
||
|
>>> np.tensordot(a, A, ((0, 1), (0, 1)))
|
||
|
array(['abbbcccccddddddd', 'aabbbbccccccdddddddd'], dtype=object)
|
||
|
|
||
|
>>> np.tensordot(a, A, ((2, 1), (1, 0)))
|
||
|
array(['acccbbdddd', 'aaaaacccccccbbbbbbdddddddd'], dtype=object)
|
||
|
|
||
|
"""
|
||
|
try:
|
||
|
iter(axes)
|
||
|
except Exception:
|
||
|
axes_a = list(range(-axes, 0))
|
||
|
axes_b = list(range(0, axes))
|
||
|
else:
|
||
|
axes_a, axes_b = axes
|
||
|
try:
|
||
|
na = len(axes_a)
|
||
|
axes_a = list(axes_a)
|
||
|
except TypeError:
|
||
|
axes_a = [axes_a]
|
||
|
na = 1
|
||
|
try:
|
||
|
nb = len(axes_b)
|
||
|
axes_b = list(axes_b)
|
||
|
except TypeError:
|
||
|
axes_b = [axes_b]
|
||
|
nb = 1
|
||
|
|
||
|
a, b = asarray(a), asarray(b)
|
||
|
as_ = a.shape
|
||
|
nda = a.ndim
|
||
|
bs = b.shape
|
||
|
ndb = b.ndim
|
||
|
equal = True
|
||
|
if na != nb:
|
||
|
equal = False
|
||
|
else:
|
||
|
for k in range(na):
|
||
|
if as_[axes_a[k]] != bs[axes_b[k]]:
|
||
|
equal = False
|
||
|
break
|
||
|
if axes_a[k] < 0:
|
||
|
axes_a[k] += nda
|
||
|
if axes_b[k] < 0:
|
||
|
axes_b[k] += ndb
|
||
|
if not equal:
|
||
|
raise ValueError("shape-mismatch for sum")
|
||
|
|
||
|
# Move the axes to sum over to the end of "a"
|
||
|
# and to the front of "b"
|
||
|
notin = [k for k in range(nda) if k not in axes_a]
|
||
|
newaxes_a = notin + axes_a
|
||
|
N2 = 1
|
||
|
for axis in axes_a:
|
||
|
N2 *= as_[axis]
|
||
|
newshape_a = (int(multiply.reduce([as_[ax] for ax in notin])), N2)
|
||
|
olda = [as_[axis] for axis in notin]
|
||
|
|
||
|
notin = [k for k in range(ndb) if k not in axes_b]
|
||
|
newaxes_b = axes_b + notin
|
||
|
N2 = 1
|
||
|
for axis in axes_b:
|
||
|
N2 *= bs[axis]
|
||
|
newshape_b = (N2, int(multiply.reduce([bs[ax] for ax in notin])))
|
||
|
oldb = [bs[axis] for axis in notin]
|
||
|
|
||
|
at = a.transpose(newaxes_a).reshape(newshape_a)
|
||
|
bt = b.transpose(newaxes_b).reshape(newshape_b)
|
||
|
res = dot(at, bt)
|
||
|
return res.reshape(olda + oldb)
|
||
|
|
||
|
|
||
|
def _roll_dispatcher(a, shift, axis=None):
|
||
|
return (a,)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_roll_dispatcher)
|
||
|
def roll(a, shift, axis=None):
|
||
|
"""
|
||
|
Roll array elements along a given axis.
|
||
|
|
||
|
Elements that roll beyond the last position are re-introduced at
|
||
|
the first.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : array_like
|
||
|
Input array.
|
||
|
shift : int or tuple of ints
|
||
|
The number of places by which elements are shifted. If a tuple,
|
||
|
then `axis` must be a tuple of the same size, and each of the
|
||
|
given axes is shifted by the corresponding number. If an int
|
||
|
while `axis` is a tuple of ints, then the same value is used for
|
||
|
all given axes.
|
||
|
axis : int or tuple of ints, optional
|
||
|
Axis or axes along which elements are shifted. By default, the
|
||
|
array is flattened before shifting, after which the original
|
||
|
shape is restored.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
res : ndarray
|
||
|
Output array, with the same shape as `a`.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
rollaxis : Roll the specified axis backwards, until it lies in a
|
||
|
given position.
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
.. versionadded:: 1.12.0
|
||
|
|
||
|
Supports rolling over multiple dimensions simultaneously.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> x = np.arange(10)
|
||
|
>>> np.roll(x, 2)
|
||
|
array([8, 9, 0, 1, 2, 3, 4, 5, 6, 7])
|
||
|
>>> np.roll(x, -2)
|
||
|
array([2, 3, 4, 5, 6, 7, 8, 9, 0, 1])
|
||
|
|
||
|
>>> x2 = np.reshape(x, (2, 5))
|
||
|
>>> x2
|
||
|
array([[0, 1, 2, 3, 4],
|
||
|
[5, 6, 7, 8, 9]])
|
||
|
>>> np.roll(x2, 1)
|
||
|
array([[9, 0, 1, 2, 3],
|
||
|
[4, 5, 6, 7, 8]])
|
||
|
>>> np.roll(x2, -1)
|
||
|
array([[1, 2, 3, 4, 5],
|
||
|
[6, 7, 8, 9, 0]])
|
||
|
>>> np.roll(x2, 1, axis=0)
|
||
|
array([[5, 6, 7, 8, 9],
|
||
|
[0, 1, 2, 3, 4]])
|
||
|
>>> np.roll(x2, -1, axis=0)
|
||
|
array([[5, 6, 7, 8, 9],
|
||
|
[0, 1, 2, 3, 4]])
|
||
|
>>> np.roll(x2, 1, axis=1)
|
||
|
array([[4, 0, 1, 2, 3],
|
||
|
[9, 5, 6, 7, 8]])
|
||
|
>>> np.roll(x2, -1, axis=1)
|
||
|
array([[1, 2, 3, 4, 0],
|
||
|
[6, 7, 8, 9, 5]])
|
||
|
>>> np.roll(x2, (1, 1), axis=(1, 0))
|
||
|
array([[9, 5, 6, 7, 8],
|
||
|
[4, 0, 1, 2, 3]])
|
||
|
>>> np.roll(x2, (2, 1), axis=(1, 0))
|
||
|
array([[8, 9, 5, 6, 7],
|
||
|
[3, 4, 0, 1, 2]])
|
||
|
|
||
|
"""
|
||
|
a = asanyarray(a)
|
||
|
if axis is None:
|
||
|
return roll(a.ravel(), shift, 0).reshape(a.shape)
|
||
|
|
||
|
else:
|
||
|
axis = normalize_axis_tuple(axis, a.ndim, allow_duplicate=True)
|
||
|
broadcasted = broadcast(shift, axis)
|
||
|
if broadcasted.ndim > 1:
|
||
|
raise ValueError(
|
||
|
"'shift' and 'axis' should be scalars or 1D sequences")
|
||
|
shifts = {ax: 0 for ax in range(a.ndim)}
|
||
|
for sh, ax in broadcasted:
|
||
|
shifts[ax] += sh
|
||
|
|
||
|
rolls = [((slice(None), slice(None)),)] * a.ndim
|
||
|
for ax, offset in shifts.items():
|
||
|
offset %= a.shape[ax] or 1 # If `a` is empty, nothing matters.
|
||
|
if offset:
|
||
|
# (original, result), (original, result)
|
||
|
rolls[ax] = ((slice(None, -offset), slice(offset, None)),
|
||
|
(slice(-offset, None), slice(None, offset)))
|
||
|
|
||
|
result = empty_like(a)
|
||
|
for indices in itertools.product(*rolls):
|
||
|
arr_index, res_index = zip(*indices)
|
||
|
result[res_index] = a[arr_index]
|
||
|
|
||
|
return result
|
||
|
|
||
|
|
||
|
def _rollaxis_dispatcher(a, axis, start=None):
|
||
|
return (a,)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_rollaxis_dispatcher)
|
||
|
def rollaxis(a, axis, start=0):
|
||
|
"""
|
||
|
Roll the specified axis backwards, until it lies in a given position.
|
||
|
|
||
|
This function continues to be supported for backward compatibility, but you
|
||
|
should prefer `moveaxis`. The `moveaxis` function was added in NumPy
|
||
|
1.11.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : ndarray
|
||
|
Input array.
|
||
|
axis : int
|
||
|
The axis to be rolled. The positions of the other axes do not
|
||
|
change relative to one another.
|
||
|
start : int, optional
|
||
|
When ``start <= axis``, the axis is rolled back until it lies in
|
||
|
this position. When ``start > axis``, the axis is rolled until it
|
||
|
lies before this position. The default, 0, results in a "complete"
|
||
|
roll. The following table describes how negative values of ``start``
|
||
|
are interpreted:
|
||
|
|
||
|
.. table::
|
||
|
:align: left
|
||
|
|
||
|
+-------------------+----------------------+
|
||
|
| ``start`` | Normalized ``start`` |
|
||
|
+===================+======================+
|
||
|
| ``-(arr.ndim+1)`` | raise ``AxisError`` |
|
||
|
+-------------------+----------------------+
|
||
|
| ``-arr.ndim`` | 0 |
|
||
|
+-------------------+----------------------+
|
||
|
| |vdots| | |vdots| |
|
||
|
+-------------------+----------------------+
|
||
|
| ``-1`` | ``arr.ndim-1`` |
|
||
|
+-------------------+----------------------+
|
||
|
| ``0`` | ``0`` |
|
||
|
+-------------------+----------------------+
|
||
|
| |vdots| | |vdots| |
|
||
|
+-------------------+----------------------+
|
||
|
| ``arr.ndim`` | ``arr.ndim`` |
|
||
|
+-------------------+----------------------+
|
||
|
| ``arr.ndim + 1`` | raise ``AxisError`` |
|
||
|
+-------------------+----------------------+
|
||
|
|
||
|
.. |vdots| unicode:: U+22EE .. Vertical Ellipsis
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
res : ndarray
|
||
|
For NumPy >= 1.10.0 a view of `a` is always returned. For earlier
|
||
|
NumPy versions a view of `a` is returned only if the order of the
|
||
|
axes is changed, otherwise the input array is returned.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
moveaxis : Move array axes to new positions.
|
||
|
roll : Roll the elements of an array by a number of positions along a
|
||
|
given axis.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> a = np.ones((3,4,5,6))
|
||
|
>>> np.rollaxis(a, 3, 1).shape
|
||
|
(3, 6, 4, 5)
|
||
|
>>> np.rollaxis(a, 2).shape
|
||
|
(5, 3, 4, 6)
|
||
|
>>> np.rollaxis(a, 1, 4).shape
|
||
|
(3, 5, 6, 4)
|
||
|
|
||
|
"""
|
||
|
n = a.ndim
|
||
|
axis = normalize_axis_index(axis, n)
|
||
|
if start < 0:
|
||
|
start += n
|
||
|
msg = "'%s' arg requires %d <= %s < %d, but %d was passed in"
|
||
|
if not (0 <= start < n + 1):
|
||
|
raise AxisError(msg % ('start', -n, 'start', n + 1, start))
|
||
|
if axis < start:
|
||
|
# it's been removed
|
||
|
start -= 1
|
||
|
if axis == start:
|
||
|
return a[...]
|
||
|
axes = list(range(0, n))
|
||
|
axes.remove(axis)
|
||
|
axes.insert(start, axis)
|
||
|
return a.transpose(axes)
|
||
|
|
||
|
|
||
|
def normalize_axis_tuple(axis, ndim, argname=None, allow_duplicate=False):
|
||
|
"""
|
||
|
Normalizes an axis argument into a tuple of non-negative integer axes.
|
||
|
|
||
|
This handles shorthands such as ``1`` and converts them to ``(1,)``,
|
||
|
as well as performing the handling of negative indices covered by
|
||
|
`normalize_axis_index`.
|
||
|
|
||
|
By default, this forbids axes from being specified multiple times.
|
||
|
|
||
|
Used internally by multi-axis-checking logic.
|
||
|
|
||
|
.. versionadded:: 1.13.0
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
axis : int, iterable of int
|
||
|
The un-normalized index or indices of the axis.
|
||
|
ndim : int
|
||
|
The number of dimensions of the array that `axis` should be normalized
|
||
|
against.
|
||
|
argname : str, optional
|
||
|
A prefix to put before the error message, typically the name of the
|
||
|
argument.
|
||
|
allow_duplicate : bool, optional
|
||
|
If False, the default, disallow an axis from being specified twice.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
normalized_axes : tuple of int
|
||
|
The normalized axis index, such that `0 <= normalized_axis < ndim`
|
||
|
|
||
|
Raises
|
||
|
------
|
||
|
AxisError
|
||
|
If any axis provided is out of range
|
||
|
ValueError
|
||
|
If an axis is repeated
|
||
|
|
||
|
See also
|
||
|
--------
|
||
|
normalize_axis_index : normalizing a single scalar axis
|
||
|
"""
|
||
|
# Optimization to speed-up the most common cases.
|
||
|
if type(axis) not in (tuple, list):
|
||
|
try:
|
||
|
axis = [operator.index(axis)]
|
||
|
except TypeError:
|
||
|
pass
|
||
|
# Going via an iterator directly is slower than via list comprehension.
|
||
|
axis = tuple([normalize_axis_index(ax, ndim, argname) for ax in axis])
|
||
|
if not allow_duplicate and len(set(axis)) != len(axis):
|
||
|
if argname:
|
||
|
raise ValueError('repeated axis in `{}` argument'.format(argname))
|
||
|
else:
|
||
|
raise ValueError('repeated axis')
|
||
|
return axis
|
||
|
|
||
|
|
||
|
def _moveaxis_dispatcher(a, source, destination):
|
||
|
return (a,)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_moveaxis_dispatcher)
|
||
|
def moveaxis(a, source, destination):
|
||
|
"""
|
||
|
Move axes of an array to new positions.
|
||
|
|
||
|
Other axes remain in their original order.
|
||
|
|
||
|
.. versionadded:: 1.11.0
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : np.ndarray
|
||
|
The array whose axes should be reordered.
|
||
|
source : int or sequence of int
|
||
|
Original positions of the axes to move. These must be unique.
|
||
|
destination : int or sequence of int
|
||
|
Destination positions for each of the original axes. These must also be
|
||
|
unique.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
result : np.ndarray
|
||
|
Array with moved axes. This array is a view of the input array.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
transpose : Permute the dimensions of an array.
|
||
|
swapaxes : Interchange two axes of an array.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> x = np.zeros((3, 4, 5))
|
||
|
>>> np.moveaxis(x, 0, -1).shape
|
||
|
(4, 5, 3)
|
||
|
>>> np.moveaxis(x, -1, 0).shape
|
||
|
(5, 3, 4)
|
||
|
|
||
|
These all achieve the same result:
|
||
|
|
||
|
>>> np.transpose(x).shape
|
||
|
(5, 4, 3)
|
||
|
>>> np.swapaxes(x, 0, -1).shape
|
||
|
(5, 4, 3)
|
||
|
>>> np.moveaxis(x, [0, 1], [-1, -2]).shape
|
||
|
(5, 4, 3)
|
||
|
>>> np.moveaxis(x, [0, 1, 2], [-1, -2, -3]).shape
|
||
|
(5, 4, 3)
|
||
|
|
||
|
"""
|
||
|
try:
|
||
|
# allow duck-array types if they define transpose
|
||
|
transpose = a.transpose
|
||
|
except AttributeError:
|
||
|
a = asarray(a)
|
||
|
transpose = a.transpose
|
||
|
|
||
|
source = normalize_axis_tuple(source, a.ndim, 'source')
|
||
|
destination = normalize_axis_tuple(destination, a.ndim, 'destination')
|
||
|
if len(source) != len(destination):
|
||
|
raise ValueError('`source` and `destination` arguments must have '
|
||
|
'the same number of elements')
|
||
|
|
||
|
order = [n for n in range(a.ndim) if n not in source]
|
||
|
|
||
|
for dest, src in sorted(zip(destination, source)):
|
||
|
order.insert(dest, src)
|
||
|
|
||
|
result = transpose(order)
|
||
|
return result
|
||
|
|
||
|
|
||
|
def _cross_dispatcher(a, b, axisa=None, axisb=None, axisc=None, axis=None):
|
||
|
return (a, b)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_cross_dispatcher)
|
||
|
def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None):
|
||
|
"""
|
||
|
Return the cross product of two (arrays of) vectors.
|
||
|
|
||
|
The cross product of `a` and `b` in :math:`R^3` is a vector perpendicular
|
||
|
to both `a` and `b`. If `a` and `b` are arrays of vectors, the vectors
|
||
|
are defined by the last axis of `a` and `b` by default, and these axes
|
||
|
can have dimensions 2 or 3. Where the dimension of either `a` or `b` is
|
||
|
2, the third component of the input vector is assumed to be zero and the
|
||
|
cross product calculated accordingly. In cases where both input vectors
|
||
|
have dimension 2, the z-component of the cross product is returned.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a : array_like
|
||
|
Components of the first vector(s).
|
||
|
b : array_like
|
||
|
Components of the second vector(s).
|
||
|
axisa : int, optional
|
||
|
Axis of `a` that defines the vector(s). By default, the last axis.
|
||
|
axisb : int, optional
|
||
|
Axis of `b` that defines the vector(s). By default, the last axis.
|
||
|
axisc : int, optional
|
||
|
Axis of `c` containing the cross product vector(s). Ignored if
|
||
|
both input vectors have dimension 2, as the return is scalar.
|
||
|
By default, the last axis.
|
||
|
axis : int, optional
|
||
|
If defined, the axis of `a`, `b` and `c` that defines the vector(s)
|
||
|
and cross product(s). Overrides `axisa`, `axisb` and `axisc`.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
c : ndarray
|
||
|
Vector cross product(s).
|
||
|
|
||
|
Raises
|
||
|
------
|
||
|
ValueError
|
||
|
When the dimension of the vector(s) in `a` and/or `b` does not
|
||
|
equal 2 or 3.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
inner : Inner product
|
||
|
outer : Outer product.
|
||
|
ix_ : Construct index arrays.
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
.. versionadded:: 1.9.0
|
||
|
|
||
|
Supports full broadcasting of the inputs.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
Vector cross-product.
|
||
|
|
||
|
>>> x = [1, 2, 3]
|
||
|
>>> y = [4, 5, 6]
|
||
|
>>> np.cross(x, y)
|
||
|
array([-3, 6, -3])
|
||
|
|
||
|
One vector with dimension 2.
|
||
|
|
||
|
>>> x = [1, 2]
|
||
|
>>> y = [4, 5, 6]
|
||
|
>>> np.cross(x, y)
|
||
|
array([12, -6, -3])
|
||
|
|
||
|
Equivalently:
|
||
|
|
||
|
>>> x = [1, 2, 0]
|
||
|
>>> y = [4, 5, 6]
|
||
|
>>> np.cross(x, y)
|
||
|
array([12, -6, -3])
|
||
|
|
||
|
Both vectors with dimension 2.
|
||
|
|
||
|
>>> x = [1,2]
|
||
|
>>> y = [4,5]
|
||
|
>>> np.cross(x, y)
|
||
|
array(-3)
|
||
|
|
||
|
Multiple vector cross-products. Note that the direction of the cross
|
||
|
product vector is defined by the *right-hand rule*.
|
||
|
|
||
|
>>> x = np.array([[1,2,3], [4,5,6]])
|
||
|
>>> y = np.array([[4,5,6], [1,2,3]])
|
||
|
>>> np.cross(x, y)
|
||
|
array([[-3, 6, -3],
|
||
|
[ 3, -6, 3]])
|
||
|
|
||
|
The orientation of `c` can be changed using the `axisc` keyword.
|
||
|
|
||
|
>>> np.cross(x, y, axisc=0)
|
||
|
array([[-3, 3],
|
||
|
[ 6, -6],
|
||
|
[-3, 3]])
|
||
|
|
||
|
Change the vector definition of `x` and `y` using `axisa` and `axisb`.
|
||
|
|
||
|
>>> x = np.array([[1,2,3], [4,5,6], [7, 8, 9]])
|
||
|
>>> y = np.array([[7, 8, 9], [4,5,6], [1,2,3]])
|
||
|
>>> np.cross(x, y)
|
||
|
array([[ -6, 12, -6],
|
||
|
[ 0, 0, 0],
|
||
|
[ 6, -12, 6]])
|
||
|
>>> np.cross(x, y, axisa=0, axisb=0)
|
||
|
array([[-24, 48, -24],
|
||
|
[-30, 60, -30],
|
||
|
[-36, 72, -36]])
|
||
|
|
||
|
"""
|
||
|
if axis is not None:
|
||
|
axisa, axisb, axisc = (axis,) * 3
|
||
|
a = asarray(a)
|
||
|
b = asarray(b)
|
||
|
# Check axisa and axisb are within bounds
|
||
|
axisa = normalize_axis_index(axisa, a.ndim, msg_prefix='axisa')
|
||
|
axisb = normalize_axis_index(axisb, b.ndim, msg_prefix='axisb')
|
||
|
|
||
|
# Move working axis to the end of the shape
|
||
|
a = moveaxis(a, axisa, -1)
|
||
|
b = moveaxis(b, axisb, -1)
|
||
|
msg = ("incompatible dimensions for cross product\n"
|
||
|
"(dimension must be 2 or 3)")
|
||
|
if a.shape[-1] not in (2, 3) or b.shape[-1] not in (2, 3):
|
||
|
raise ValueError(msg)
|
||
|
|
||
|
# Create the output array
|
||
|
shape = broadcast(a[..., 0], b[..., 0]).shape
|
||
|
if a.shape[-1] == 3 or b.shape[-1] == 3:
|
||
|
shape += (3,)
|
||
|
# Check axisc is within bounds
|
||
|
axisc = normalize_axis_index(axisc, len(shape), msg_prefix='axisc')
|
||
|
dtype = promote_types(a.dtype, b.dtype)
|
||
|
cp = empty(shape, dtype)
|
||
|
|
||
|
# recast arrays as dtype
|
||
|
a = a.astype(dtype)
|
||
|
b = b.astype(dtype)
|
||
|
|
||
|
# create local aliases for readability
|
||
|
a0 = a[..., 0]
|
||
|
a1 = a[..., 1]
|
||
|
if a.shape[-1] == 3:
|
||
|
a2 = a[..., 2]
|
||
|
b0 = b[..., 0]
|
||
|
b1 = b[..., 1]
|
||
|
if b.shape[-1] == 3:
|
||
|
b2 = b[..., 2]
|
||
|
if cp.ndim != 0 and cp.shape[-1] == 3:
|
||
|
cp0 = cp[..., 0]
|
||
|
cp1 = cp[..., 1]
|
||
|
cp2 = cp[..., 2]
|
||
|
|
||
|
if a.shape[-1] == 2:
|
||
|
if b.shape[-1] == 2:
|
||
|
# a0 * b1 - a1 * b0
|
||
|
multiply(a0, b1, out=cp)
|
||
|
cp -= a1 * b0
|
||
|
return cp
|
||
|
else:
|
||
|
assert b.shape[-1] == 3
|
||
|
# cp0 = a1 * b2 - 0 (a2 = 0)
|
||
|
# cp1 = 0 - a0 * b2 (a2 = 0)
|
||
|
# cp2 = a0 * b1 - a1 * b0
|
||
|
multiply(a1, b2, out=cp0)
|
||
|
multiply(a0, b2, out=cp1)
|
||
|
negative(cp1, out=cp1)
|
||
|
multiply(a0, b1, out=cp2)
|
||
|
cp2 -= a1 * b0
|
||
|
else:
|
||
|
assert a.shape[-1] == 3
|
||
|
if b.shape[-1] == 3:
|
||
|
# cp0 = a1 * b2 - a2 * b1
|
||
|
# cp1 = a2 * b0 - a0 * b2
|
||
|
# cp2 = a0 * b1 - a1 * b0
|
||
|
multiply(a1, b2, out=cp0)
|
||
|
tmp = array(a2 * b1)
|
||
|
cp0 -= tmp
|
||
|
multiply(a2, b0, out=cp1)
|
||
|
multiply(a0, b2, out=tmp)
|
||
|
cp1 -= tmp
|
||
|
multiply(a0, b1, out=cp2)
|
||
|
multiply(a1, b0, out=tmp)
|
||
|
cp2 -= tmp
|
||
|
else:
|
||
|
assert b.shape[-1] == 2
|
||
|
# cp0 = 0 - a2 * b1 (b2 = 0)
|
||
|
# cp1 = a2 * b0 - 0 (b2 = 0)
|
||
|
# cp2 = a0 * b1 - a1 * b0
|
||
|
multiply(a2, b1, out=cp0)
|
||
|
negative(cp0, out=cp0)
|
||
|
multiply(a2, b0, out=cp1)
|
||
|
multiply(a0, b1, out=cp2)
|
||
|
cp2 -= a1 * b0
|
||
|
|
||
|
return moveaxis(cp, -1, axisc)
|
||
|
|
||
|
|
||
|
little_endian = (sys.byteorder == 'little')
|
||
|
|
||
|
|
||
|
@set_module('numpy')
|
||
|
def indices(dimensions, dtype=int, sparse=False):
|
||
|
"""
|
||
|
Return an array representing the indices of a grid.
|
||
|
|
||
|
Compute an array where the subarrays contain index values 0, 1, ...
|
||
|
varying only along the corresponding axis.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
dimensions : sequence of ints
|
||
|
The shape of the grid.
|
||
|
dtype : dtype, optional
|
||
|
Data type of the result.
|
||
|
sparse : boolean, optional
|
||
|
Return a sparse representation of the grid instead of a dense
|
||
|
representation. Default is False.
|
||
|
|
||
|
.. versionadded:: 1.17
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
grid : one ndarray or tuple of ndarrays
|
||
|
If sparse is False:
|
||
|
Returns one array of grid indices,
|
||
|
``grid.shape = (len(dimensions),) + tuple(dimensions)``.
|
||
|
If sparse is True:
|
||
|
Returns a tuple of arrays, with
|
||
|
``grid[i].shape = (1, ..., 1, dimensions[i], 1, ..., 1)`` with
|
||
|
dimensions[i] in the ith place
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
mgrid, ogrid, meshgrid
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
The output shape in the dense case is obtained by prepending the number
|
||
|
of dimensions in front of the tuple of dimensions, i.e. if `dimensions`
|
||
|
is a tuple ``(r0, ..., rN-1)`` of length ``N``, the output shape is
|
||
|
``(N, r0, ..., rN-1)``.
|
||
|
|
||
|
The subarrays ``grid[k]`` contains the N-D array of indices along the
|
||
|
``k-th`` axis. Explicitly::
|
||
|
|
||
|
grid[k, i0, i1, ..., iN-1] = ik
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> grid = np.indices((2, 3))
|
||
|
>>> grid.shape
|
||
|
(2, 2, 3)
|
||
|
>>> grid[0] # row indices
|
||
|
array([[0, 0, 0],
|
||
|
[1, 1, 1]])
|
||
|
>>> grid[1] # column indices
|
||
|
array([[0, 1, 2],
|
||
|
[0, 1, 2]])
|
||
|
|
||
|
The indices can be used as an index into an array.
|
||
|
|
||
|
>>> x = np.arange(20).reshape(5, 4)
|
||
|
>>> row, col = np.indices((2, 3))
|
||
|
>>> x[row, col]
|
||
|
array([[0, 1, 2],
|
||
|
[4, 5, 6]])
|
||
|
|
||
|
Note that it would be more straightforward in the above example to
|
||
|
extract the required elements directly with ``x[:2, :3]``.
|
||
|
|
||
|
If sparse is set to true, the grid will be returned in a sparse
|
||
|
representation.
|
||
|
|
||
|
>>> i, j = np.indices((2, 3), sparse=True)
|
||
|
>>> i.shape
|
||
|
(2, 1)
|
||
|
>>> j.shape
|
||
|
(1, 3)
|
||
|
>>> i # row indices
|
||
|
array([[0],
|
||
|
[1]])
|
||
|
>>> j # column indices
|
||
|
array([[0, 1, 2]])
|
||
|
|
||
|
"""
|
||
|
dimensions = tuple(dimensions)
|
||
|
N = len(dimensions)
|
||
|
shape = (1,)*N
|
||
|
if sparse:
|
||
|
res = tuple()
|
||
|
else:
|
||
|
res = empty((N,)+dimensions, dtype=dtype)
|
||
|
for i, dim in enumerate(dimensions):
|
||
|
idx = arange(dim, dtype=dtype).reshape(
|
||
|
shape[:i] + (dim,) + shape[i+1:]
|
||
|
)
|
||
|
if sparse:
|
||
|
res = res + (idx,)
|
||
|
else:
|
||
|
res[i] = idx
|
||
|
return res
|
||
|
|
||
|
|
||
|
@set_array_function_like_doc
|
||
|
@set_module('numpy')
|
||
|
def fromfunction(function, shape, *, dtype=float, like=None, **kwargs):
|
||
|
"""
|
||
|
Construct an array by executing a function over each coordinate.
|
||
|
|
||
|
The resulting array therefore has a value ``fn(x, y, z)`` at
|
||
|
coordinate ``(x, y, z)``.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
function : callable
|
||
|
The function is called with N parameters, where N is the rank of
|
||
|
`shape`. Each parameter represents the coordinates of the array
|
||
|
varying along a specific axis. For example, if `shape`
|
||
|
were ``(2, 2)``, then the parameters would be
|
||
|
``array([[0, 0], [1, 1]])`` and ``array([[0, 1], [0, 1]])``
|
||
|
shape : (N,) tuple of ints
|
||
|
Shape of the output array, which also determines the shape of
|
||
|
the coordinate arrays passed to `function`.
|
||
|
dtype : data-type, optional
|
||
|
Data-type of the coordinate arrays passed to `function`.
|
||
|
By default, `dtype` is float.
|
||
|
${ARRAY_FUNCTION_LIKE}
|
||
|
|
||
|
.. versionadded:: 1.20.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
fromfunction : any
|
||
|
The result of the call to `function` is passed back directly.
|
||
|
Therefore the shape of `fromfunction` is completely determined by
|
||
|
`function`. If `function` returns a scalar value, the shape of
|
||
|
`fromfunction` would not match the `shape` parameter.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
indices, meshgrid
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
Keywords other than `dtype` and `like` are passed to `function`.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.fromfunction(lambda i, j: i, (2, 2), dtype=float)
|
||
|
array([[0., 0.],
|
||
|
[1., 1.]])
|
||
|
|
||
|
>>> np.fromfunction(lambda i, j: j, (2, 2), dtype=float)
|
||
|
array([[0., 1.],
|
||
|
[0., 1.]])
|
||
|
|
||
|
>>> np.fromfunction(lambda i, j: i == j, (3, 3), dtype=int)
|
||
|
array([[ True, False, False],
|
||
|
[False, True, False],
|
||
|
[False, False, True]])
|
||
|
|
||
|
>>> np.fromfunction(lambda i, j: i + j, (3, 3), dtype=int)
|
||
|
array([[0, 1, 2],
|
||
|
[1, 2, 3],
|
||
|
[2, 3, 4]])
|
||
|
|
||
|
"""
|
||
|
if like is not None:
|
||
|
return _fromfunction_with_like(
|
||
|
like, function, shape, dtype=dtype, **kwargs)
|
||
|
|
||
|
args = indices(shape, dtype=dtype)
|
||
|
return function(*args, **kwargs)
|
||
|
|
||
|
|
||
|
_fromfunction_with_like = array_function_dispatch()(fromfunction)
|
||
|
|
||
|
|
||
|
def _frombuffer(buf, dtype, shape, order):
|
||
|
return frombuffer(buf, dtype=dtype).reshape(shape, order=order)
|
||
|
|
||
|
|
||
|
@set_module('numpy')
|
||
|
def isscalar(element):
|
||
|
"""
|
||
|
Returns True if the type of `element` is a scalar type.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
element : any
|
||
|
Input argument, can be of any type and shape.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
val : bool
|
||
|
True if `element` is a scalar type, False if it is not.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
ndim : Get the number of dimensions of an array
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
If you need a stricter way to identify a *numerical* scalar, use
|
||
|
``isinstance(x, numbers.Number)``, as that returns ``False`` for most
|
||
|
non-numerical elements such as strings.
|
||
|
|
||
|
In most cases ``np.ndim(x) == 0`` should be used instead of this function,
|
||
|
as that will also return true for 0d arrays. This is how numpy overloads
|
||
|
functions in the style of the ``dx`` arguments to `gradient` and the ``bins``
|
||
|
argument to `histogram`. Some key differences:
|
||
|
|
||
|
+--------------------------------------+---------------+-------------------+
|
||
|
| x |``isscalar(x)``|``np.ndim(x) == 0``|
|
||
|
+======================================+===============+===================+
|
||
|
| PEP 3141 numeric objects (including | ``True`` | ``True`` |
|
||
|
| builtins) | | |
|
||
|
+--------------------------------------+---------------+-------------------+
|
||
|
| builtin string and buffer objects | ``True`` | ``True`` |
|
||
|
+--------------------------------------+---------------+-------------------+
|
||
|
| other builtin objects, like | ``False`` | ``True`` |
|
||
|
| `pathlib.Path`, `Exception`, | | |
|
||
|
| the result of `re.compile` | | |
|
||
|
+--------------------------------------+---------------+-------------------+
|
||
|
| third-party objects like | ``False`` | ``True`` |
|
||
|
| `matplotlib.figure.Figure` | | |
|
||
|
+--------------------------------------+---------------+-------------------+
|
||
|
| zero-dimensional numpy arrays | ``False`` | ``True`` |
|
||
|
+--------------------------------------+---------------+-------------------+
|
||
|
| other numpy arrays | ``False`` | ``False`` |
|
||
|
+--------------------------------------+---------------+-------------------+
|
||
|
| `list`, `tuple`, and other sequence | ``False`` | ``False`` |
|
||
|
| objects | | |
|
||
|
+--------------------------------------+---------------+-------------------+
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.isscalar(3.1)
|
||
|
True
|
||
|
>>> np.isscalar(np.array(3.1))
|
||
|
False
|
||
|
>>> np.isscalar([3.1])
|
||
|
False
|
||
|
>>> np.isscalar(False)
|
||
|
True
|
||
|
>>> np.isscalar('numpy')
|
||
|
True
|
||
|
|
||
|
NumPy supports PEP 3141 numbers:
|
||
|
|
||
|
>>> from fractions import Fraction
|
||
|
>>> np.isscalar(Fraction(5, 17))
|
||
|
True
|
||
|
>>> from numbers import Number
|
||
|
>>> np.isscalar(Number())
|
||
|
True
|
||
|
|
||
|
"""
|
||
|
return (isinstance(element, generic)
|
||
|
or type(element) in ScalarType
|
||
|
or isinstance(element, numbers.Number))
|
||
|
|
||
|
|
||
|
@set_module('numpy')
|
||
|
def binary_repr(num, width=None):
|
||
|
"""
|
||
|
Return the binary representation of the input number as a string.
|
||
|
|
||
|
For negative numbers, if width is not given, a minus sign is added to the
|
||
|
front. If width is given, the two's complement of the number is
|
||
|
returned, with respect to that width.
|
||
|
|
||
|
In a two's-complement system negative numbers are represented by the two's
|
||
|
complement of the absolute value. This is the most common method of
|
||
|
representing signed integers on computers [1]_. A N-bit two's-complement
|
||
|
system can represent every integer in the range
|
||
|
:math:`-2^{N-1}` to :math:`+2^{N-1}-1`.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
num : int
|
||
|
Only an integer decimal number can be used.
|
||
|
width : int, optional
|
||
|
The length of the returned string if `num` is positive, or the length
|
||
|
of the two's complement if `num` is negative, provided that `width` is
|
||
|
at least a sufficient number of bits for `num` to be represented in the
|
||
|
designated form.
|
||
|
|
||
|
If the `width` value is insufficient, it will be ignored, and `num` will
|
||
|
be returned in binary (`num` > 0) or two's complement (`num` < 0) form
|
||
|
with its width equal to the minimum number of bits needed to represent
|
||
|
the number in the designated form. This behavior is deprecated and will
|
||
|
later raise an error.
|
||
|
|
||
|
.. deprecated:: 1.12.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
bin : str
|
||
|
Binary representation of `num` or two's complement of `num`.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
base_repr: Return a string representation of a number in the given base
|
||
|
system.
|
||
|
bin: Python's built-in binary representation generator of an integer.
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
`binary_repr` is equivalent to using `base_repr` with base 2, but about 25x
|
||
|
faster.
|
||
|
|
||
|
References
|
||
|
----------
|
||
|
.. [1] Wikipedia, "Two's complement",
|
||
|
https://en.wikipedia.org/wiki/Two's_complement
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.binary_repr(3)
|
||
|
'11'
|
||
|
>>> np.binary_repr(-3)
|
||
|
'-11'
|
||
|
>>> np.binary_repr(3, width=4)
|
||
|
'0011'
|
||
|
|
||
|
The two's complement is returned when the input number is negative and
|
||
|
width is specified:
|
||
|
|
||
|
>>> np.binary_repr(-3, width=3)
|
||
|
'101'
|
||
|
>>> np.binary_repr(-3, width=5)
|
||
|
'11101'
|
||
|
|
||
|
"""
|
||
|
def warn_if_insufficient(width, binwidth):
|
||
|
if width is not None and width < binwidth:
|
||
|
warnings.warn(
|
||
|
"Insufficient bit width provided. This behavior "
|
||
|
"will raise an error in the future.", DeprecationWarning,
|
||
|
stacklevel=3)
|
||
|
|
||
|
# Ensure that num is a Python integer to avoid overflow or unwanted
|
||
|
# casts to floating point.
|
||
|
num = operator.index(num)
|
||
|
|
||
|
if num == 0:
|
||
|
return '0' * (width or 1)
|
||
|
|
||
|
elif num > 0:
|
||
|
binary = bin(num)[2:]
|
||
|
binwidth = len(binary)
|
||
|
outwidth = (binwidth if width is None
|
||
|
else builtins.max(binwidth, width))
|
||
|
warn_if_insufficient(width, binwidth)
|
||
|
return binary.zfill(outwidth)
|
||
|
|
||
|
else:
|
||
|
if width is None:
|
||
|
return '-' + bin(-num)[2:]
|
||
|
|
||
|
else:
|
||
|
poswidth = len(bin(-num)[2:])
|
||
|
|
||
|
# See gh-8679: remove extra digit
|
||
|
# for numbers at boundaries.
|
||
|
if 2**(poswidth - 1) == -num:
|
||
|
poswidth -= 1
|
||
|
|
||
|
twocomp = 2**(poswidth + 1) + num
|
||
|
binary = bin(twocomp)[2:]
|
||
|
binwidth = len(binary)
|
||
|
|
||
|
outwidth = builtins.max(binwidth, width)
|
||
|
warn_if_insufficient(width, binwidth)
|
||
|
return '1' * (outwidth - binwidth) + binary
|
||
|
|
||
|
|
||
|
@set_module('numpy')
|
||
|
def base_repr(number, base=2, padding=0):
|
||
|
"""
|
||
|
Return a string representation of a number in the given base system.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
number : int
|
||
|
The value to convert. Positive and negative values are handled.
|
||
|
base : int, optional
|
||
|
Convert `number` to the `base` number system. The valid range is 2-36,
|
||
|
the default value is 2.
|
||
|
padding : int, optional
|
||
|
Number of zeros padded on the left. Default is 0 (no padding).
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
out : str
|
||
|
String representation of `number` in `base` system.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
binary_repr : Faster version of `base_repr` for base 2.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.base_repr(5)
|
||
|
'101'
|
||
|
>>> np.base_repr(6, 5)
|
||
|
'11'
|
||
|
>>> np.base_repr(7, base=5, padding=3)
|
||
|
'00012'
|
||
|
|
||
|
>>> np.base_repr(10, base=16)
|
||
|
'A'
|
||
|
>>> np.base_repr(32, base=16)
|
||
|
'20'
|
||
|
|
||
|
"""
|
||
|
digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||
|
if base > len(digits):
|
||
|
raise ValueError("Bases greater than 36 not handled in base_repr.")
|
||
|
elif base < 2:
|
||
|
raise ValueError("Bases less than 2 not handled in base_repr.")
|
||
|
|
||
|
num = abs(number)
|
||
|
res = []
|
||
|
while num:
|
||
|
res.append(digits[num % base])
|
||
|
num //= base
|
||
|
if padding:
|
||
|
res.append('0' * padding)
|
||
|
if number < 0:
|
||
|
res.append('-')
|
||
|
return ''.join(reversed(res or '0'))
|
||
|
|
||
|
|
||
|
# These are all essentially abbreviations
|
||
|
# These might wind up in a special abbreviations module
|
||
|
|
||
|
|
||
|
def _maketup(descr, val):
|
||
|
dt = dtype(descr)
|
||
|
# Place val in all scalar tuples:
|
||
|
fields = dt.fields
|
||
|
if fields is None:
|
||
|
return val
|
||
|
else:
|
||
|
res = [_maketup(fields[name][0], val) for name in dt.names]
|
||
|
return tuple(res)
|
||
|
|
||
|
|
||
|
@set_array_function_like_doc
|
||
|
@set_module('numpy')
|
||
|
def identity(n, dtype=None, *, like=None):
|
||
|
"""
|
||
|
Return the identity array.
|
||
|
|
||
|
The identity array is a square array with ones on
|
||
|
the main diagonal.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
n : int
|
||
|
Number of rows (and columns) in `n` x `n` output.
|
||
|
dtype : data-type, optional
|
||
|
Data-type of the output. Defaults to ``float``.
|
||
|
${ARRAY_FUNCTION_LIKE}
|
||
|
|
||
|
.. versionadded:: 1.20.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
out : ndarray
|
||
|
`n` x `n` array with its main diagonal set to one,
|
||
|
and all other elements 0.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.identity(3)
|
||
|
array([[1., 0., 0.],
|
||
|
[0., 1., 0.],
|
||
|
[0., 0., 1.]])
|
||
|
|
||
|
"""
|
||
|
if like is not None:
|
||
|
return _identity_with_like(like, n, dtype=dtype)
|
||
|
|
||
|
from numpy import eye
|
||
|
return eye(n, dtype=dtype, like=like)
|
||
|
|
||
|
|
||
|
_identity_with_like = array_function_dispatch()(identity)
|
||
|
|
||
|
|
||
|
def _allclose_dispatcher(a, b, rtol=None, atol=None, equal_nan=None):
|
||
|
return (a, b)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_allclose_dispatcher)
|
||
|
def allclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False):
|
||
|
"""
|
||
|
Returns True if two arrays are element-wise equal within a tolerance.
|
||
|
|
||
|
The tolerance values are positive, typically very small numbers. The
|
||
|
relative difference (`rtol` * abs(`b`)) and the absolute difference
|
||
|
`atol` are added together to compare against the absolute difference
|
||
|
between `a` and `b`.
|
||
|
|
||
|
NaNs are treated as equal if they are in the same place and if
|
||
|
``equal_nan=True``. Infs are treated as equal if they are in the same
|
||
|
place and of the same sign in both arrays.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a, b : array_like
|
||
|
Input arrays to compare.
|
||
|
rtol : float
|
||
|
The relative tolerance parameter (see Notes).
|
||
|
atol : float
|
||
|
The absolute tolerance parameter (see Notes).
|
||
|
equal_nan : bool
|
||
|
Whether to compare NaN's as equal. If True, NaN's in `a` will be
|
||
|
considered equal to NaN's in `b` in the output array.
|
||
|
|
||
|
.. versionadded:: 1.10.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
allclose : bool
|
||
|
Returns True if the two arrays are equal within the given
|
||
|
tolerance; False otherwise.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
isclose, all, any, equal
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
If the following equation is element-wise True, then allclose returns
|
||
|
True.
|
||
|
|
||
|
absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`))
|
||
|
|
||
|
The above equation is not symmetric in `a` and `b`, so that
|
||
|
``allclose(a, b)`` might be different from ``allclose(b, a)`` in
|
||
|
some rare cases.
|
||
|
|
||
|
The comparison of `a` and `b` uses standard broadcasting, which
|
||
|
means that `a` and `b` need not have the same shape in order for
|
||
|
``allclose(a, b)`` to evaluate to True. The same is true for
|
||
|
`equal` but not `array_equal`.
|
||
|
|
||
|
`allclose` is not defined for non-numeric data types.
|
||
|
`bool` is considered a numeric data-type for this purpose.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.allclose([1e10,1e-7], [1.00001e10,1e-8])
|
||
|
False
|
||
|
>>> np.allclose([1e10,1e-8], [1.00001e10,1e-9])
|
||
|
True
|
||
|
>>> np.allclose([1e10,1e-8], [1.0001e10,1e-9])
|
||
|
False
|
||
|
>>> np.allclose([1.0, np.nan], [1.0, np.nan])
|
||
|
False
|
||
|
>>> np.allclose([1.0, np.nan], [1.0, np.nan], equal_nan=True)
|
||
|
True
|
||
|
|
||
|
"""
|
||
|
res = all(isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan))
|
||
|
return bool(res)
|
||
|
|
||
|
|
||
|
def _isclose_dispatcher(a, b, rtol=None, atol=None, equal_nan=None):
|
||
|
return (a, b)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_isclose_dispatcher)
|
||
|
def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False):
|
||
|
"""
|
||
|
Returns a boolean array where two arrays are element-wise equal within a
|
||
|
tolerance.
|
||
|
|
||
|
The tolerance values are positive, typically very small numbers. The
|
||
|
relative difference (`rtol` * abs(`b`)) and the absolute difference
|
||
|
`atol` are added together to compare against the absolute difference
|
||
|
between `a` and `b`.
|
||
|
|
||
|
.. warning:: The default `atol` is not appropriate for comparing numbers
|
||
|
that are much smaller than one (see Notes).
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a, b : array_like
|
||
|
Input arrays to compare.
|
||
|
rtol : float
|
||
|
The relative tolerance parameter (see Notes).
|
||
|
atol : float
|
||
|
The absolute tolerance parameter (see Notes).
|
||
|
equal_nan : bool
|
||
|
Whether to compare NaN's as equal. If True, NaN's in `a` will be
|
||
|
considered equal to NaN's in `b` in the output array.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
y : array_like
|
||
|
Returns a boolean array of where `a` and `b` are equal within the
|
||
|
given tolerance. If both `a` and `b` are scalars, returns a single
|
||
|
boolean value.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
allclose
|
||
|
math.isclose
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
.. versionadded:: 1.7.0
|
||
|
|
||
|
For finite values, isclose uses the following equation to test whether
|
||
|
two floating point values are equivalent.
|
||
|
|
||
|
absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`))
|
||
|
|
||
|
Unlike the built-in `math.isclose`, the above equation is not symmetric
|
||
|
in `a` and `b` -- it assumes `b` is the reference value -- so that
|
||
|
`isclose(a, b)` might be different from `isclose(b, a)`. Furthermore,
|
||
|
the default value of atol is not zero, and is used to determine what
|
||
|
small values should be considered close to zero. The default value is
|
||
|
appropriate for expected values of order unity: if the expected values
|
||
|
are significantly smaller than one, it can result in false positives.
|
||
|
`atol` should be carefully selected for the use case at hand. A zero value
|
||
|
for `atol` will result in `False` if either `a` or `b` is zero.
|
||
|
|
||
|
`isclose` is not defined for non-numeric data types.
|
||
|
`bool` is considered a numeric data-type for this purpose.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.isclose([1e10,1e-7], [1.00001e10,1e-8])
|
||
|
array([ True, False])
|
||
|
>>> np.isclose([1e10,1e-8], [1.00001e10,1e-9])
|
||
|
array([ True, True])
|
||
|
>>> np.isclose([1e10,1e-8], [1.0001e10,1e-9])
|
||
|
array([False, True])
|
||
|
>>> np.isclose([1.0, np.nan], [1.0, np.nan])
|
||
|
array([ True, False])
|
||
|
>>> np.isclose([1.0, np.nan], [1.0, np.nan], equal_nan=True)
|
||
|
array([ True, True])
|
||
|
>>> np.isclose([1e-8, 1e-7], [0.0, 0.0])
|
||
|
array([ True, False])
|
||
|
>>> np.isclose([1e-100, 1e-7], [0.0, 0.0], atol=0.0)
|
||
|
array([False, False])
|
||
|
>>> np.isclose([1e-10, 1e-10], [1e-20, 0.0])
|
||
|
array([ True, True])
|
||
|
>>> np.isclose([1e-10, 1e-10], [1e-20, 0.999999e-10], atol=0.0)
|
||
|
array([False, True])
|
||
|
"""
|
||
|
def within_tol(x, y, atol, rtol):
|
||
|
with errstate(invalid='ignore'), _no_nep50_warning():
|
||
|
return less_equal(abs(x-y), atol + rtol * abs(y))
|
||
|
|
||
|
x = asanyarray(a)
|
||
|
y = asanyarray(b)
|
||
|
|
||
|
# Make sure y is an inexact type to avoid bad behavior on abs(MIN_INT).
|
||
|
# This will cause casting of x later. Also, make sure to allow subclasses
|
||
|
# (e.g., for numpy.ma).
|
||
|
# NOTE: We explicitly allow timedelta, which used to work. This could
|
||
|
# possibly be deprecated. See also gh-18286.
|
||
|
# timedelta works if `atol` is an integer or also a timedelta.
|
||
|
# Although, the default tolerances are unlikely to be useful
|
||
|
if y.dtype.kind != "m":
|
||
|
dt = multiarray.result_type(y, 1.)
|
||
|
y = asanyarray(y, dtype=dt)
|
||
|
|
||
|
xfin = isfinite(x)
|
||
|
yfin = isfinite(y)
|
||
|
if all(xfin) and all(yfin):
|
||
|
return within_tol(x, y, atol, rtol)
|
||
|
else:
|
||
|
finite = xfin & yfin
|
||
|
cond = zeros_like(finite, subok=True)
|
||
|
# Because we're using boolean indexing, x & y must be the same shape.
|
||
|
# Ideally, we'd just do x, y = broadcast_arrays(x, y). It's in
|
||
|
# lib.stride_tricks, though, so we can't import it here.
|
||
|
x = x * ones_like(cond)
|
||
|
y = y * ones_like(cond)
|
||
|
# Avoid subtraction with infinite/nan values...
|
||
|
cond[finite] = within_tol(x[finite], y[finite], atol, rtol)
|
||
|
# Check for equality of infinite values...
|
||
|
cond[~finite] = (x[~finite] == y[~finite])
|
||
|
if equal_nan:
|
||
|
# Make NaN == NaN
|
||
|
both_nan = isnan(x) & isnan(y)
|
||
|
|
||
|
# Needed to treat masked arrays correctly. = True would not work.
|
||
|
cond[both_nan] = both_nan[both_nan]
|
||
|
|
||
|
return cond[()] # Flatten 0d arrays to scalars
|
||
|
|
||
|
|
||
|
def _array_equal_dispatcher(a1, a2, equal_nan=None):
|
||
|
return (a1, a2)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_array_equal_dispatcher)
|
||
|
def array_equal(a1, a2, equal_nan=False):
|
||
|
"""
|
||
|
True if two arrays have the same shape and elements, False otherwise.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a1, a2 : array_like
|
||
|
Input arrays.
|
||
|
equal_nan : bool
|
||
|
Whether to compare NaN's as equal. If the dtype of a1 and a2 is
|
||
|
complex, values will be considered equal if either the real or the
|
||
|
imaginary component of a given value is ``nan``.
|
||
|
|
||
|
.. versionadded:: 1.19.0
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
b : bool
|
||
|
Returns True if the arrays are equal.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
allclose: Returns True if two arrays are element-wise equal within a
|
||
|
tolerance.
|
||
|
array_equiv: Returns True if input arrays are shape consistent and all
|
||
|
elements equal.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.array_equal([1, 2], [1, 2])
|
||
|
True
|
||
|
>>> np.array_equal(np.array([1, 2]), np.array([1, 2]))
|
||
|
True
|
||
|
>>> np.array_equal([1, 2], [1, 2, 3])
|
||
|
False
|
||
|
>>> np.array_equal([1, 2], [1, 4])
|
||
|
False
|
||
|
>>> a = np.array([1, np.nan])
|
||
|
>>> np.array_equal(a, a)
|
||
|
False
|
||
|
>>> np.array_equal(a, a, equal_nan=True)
|
||
|
True
|
||
|
|
||
|
When ``equal_nan`` is True, complex values with nan components are
|
||
|
considered equal if either the real *or* the imaginary components are nan.
|
||
|
|
||
|
>>> a = np.array([1 + 1j])
|
||
|
>>> b = a.copy()
|
||
|
>>> a.real = np.nan
|
||
|
>>> b.imag = np.nan
|
||
|
>>> np.array_equal(a, b, equal_nan=True)
|
||
|
True
|
||
|
"""
|
||
|
try:
|
||
|
a1, a2 = asarray(a1), asarray(a2)
|
||
|
except Exception:
|
||
|
return False
|
||
|
if a1.shape != a2.shape:
|
||
|
return False
|
||
|
if not equal_nan:
|
||
|
return bool(asarray(a1 == a2).all())
|
||
|
# Handling NaN values if equal_nan is True
|
||
|
a1nan, a2nan = isnan(a1), isnan(a2)
|
||
|
# NaN's occur at different locations
|
||
|
if not (a1nan == a2nan).all():
|
||
|
return False
|
||
|
# Shapes of a1, a2 and masks are guaranteed to be consistent by this point
|
||
|
return bool(asarray(a1[~a1nan] == a2[~a1nan]).all())
|
||
|
|
||
|
|
||
|
def _array_equiv_dispatcher(a1, a2):
|
||
|
return (a1, a2)
|
||
|
|
||
|
|
||
|
@array_function_dispatch(_array_equiv_dispatcher)
|
||
|
def array_equiv(a1, a2):
|
||
|
"""
|
||
|
Returns True if input arrays are shape consistent and all elements equal.
|
||
|
|
||
|
Shape consistent means they are either the same shape, or one input array
|
||
|
can be broadcasted to create the same shape as the other one.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
a1, a2 : array_like
|
||
|
Input arrays.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
out : bool
|
||
|
True if equivalent, False otherwise.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> np.array_equiv([1, 2], [1, 2])
|
||
|
True
|
||
|
>>> np.array_equiv([1, 2], [1, 3])
|
||
|
False
|
||
|
|
||
|
Showing the shape equivalence:
|
||
|
|
||
|
>>> np.array_equiv([1, 2], [[1, 2], [1, 2]])
|
||
|
True
|
||
|
>>> np.array_equiv([1, 2], [[1, 2, 1, 2], [1, 2, 1, 2]])
|
||
|
False
|
||
|
|
||
|
>>> np.array_equiv([1, 2], [[1, 2], [1, 3]])
|
||
|
False
|
||
|
|
||
|
"""
|
||
|
try:
|
||
|
a1, a2 = asarray(a1), asarray(a2)
|
||
|
except Exception:
|
||
|
return False
|
||
|
try:
|
||
|
multiarray.broadcast(a1, a2)
|
||
|
except Exception:
|
||
|
return False
|
||
|
|
||
|
return bool(asarray(a1 == a2).all())
|
||
|
|
||
|
|
||
|
Inf = inf = infty = Infinity = PINF
|
||
|
nan = NaN = NAN
|
||
|
False_ = bool_(False)
|
||
|
True_ = bool_(True)
|
||
|
|
||
|
|
||
|
def extend_all(module):
|
||
|
existing = set(__all__)
|
||
|
mall = getattr(module, '__all__')
|
||
|
for a in mall:
|
||
|
if a not in existing:
|
||
|
__all__.append(a)
|
||
|
|
||
|
|
||
|
from .umath import *
|
||
|
from .numerictypes import *
|
||
|
from . import fromnumeric
|
||
|
from .fromnumeric import *
|
||
|
from . import arrayprint
|
||
|
from .arrayprint import *
|
||
|
from . import _asarray
|
||
|
from ._asarray import *
|
||
|
from . import _ufunc_config
|
||
|
from ._ufunc_config import *
|
||
|
extend_all(fromnumeric)
|
||
|
extend_all(umath)
|
||
|
extend_all(numerictypes)
|
||
|
extend_all(arrayprint)
|
||
|
extend_all(_asarray)
|
||
|
extend_all(_ufunc_config)
|