From f2b830d4c1133d8ff5cfbf62b3161e7c4bb68ce3 Mon Sep 17 00:00:00 2001 From: Hameer Abbasi <2190658+hameerabbasi@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:05:43 +0200 Subject: [PATCH] Edit outdated docs to pass doctests. --- .github/workflows/ci.yml | 2 +- sparse/mlir_backend/tests/__init__.py | 0 sparse/numba_backend/_common.py | 797 +----------------- .../numba_backend/_compressed/compressed.py | 2 +- sparse/numba_backend/_coo/common.py | 12 +- sparse/numba_backend/_coo/core.py | 25 +- sparse/numba_backend/_coo/indexing.py | 16 +- sparse/numba_backend/_dok.py | 1 + sparse/numba_backend/_sparse_array.py | 4 +- sparse/numba_backend/_utils.py | 31 +- sparse/numba_backend/tests/__init__.py | 0 sparse/numba_backend/tests/test_coo.py | 7 +- 12 files changed, 60 insertions(+), 837 deletions(-) create mode 100644 sparse/mlir_backend/tests/__init__.py create mode 100644 sparse/numba_backend/tests/__init__.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7497d219..6a16950a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: pip install -e '.[tests]' - name: Run tests run: | - SPARSE_BACKEND=Numba pytest --pyargs sparse --cov-report=xml:coverage_Numba.xml -n auto -vvv + SPARSE_BACKEND=Numba pytest --pyargs sparse --doctest-modules --cov-report=xml:coverage_Numba.xml -n auto -vvv SPARSE_BACKEND=Finch pytest --pyargs sparse/tests --cov-report=xml:coverage_Finch.xml -n auto -vvv SPARSE_BACKEND=MLIR pytest --pyargs sparse/mlir_backend --cov-report=xml:coverage_MLIR.xml -n auto -vvv - uses: codecov/codecov-action@v4 diff --git a/sparse/mlir_backend/tests/__init__.py b/sparse/mlir_backend/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/sparse/numba_backend/_common.py b/sparse/numba_backend/_common.py index d3440426..37a2a685 100644 --- a/sparse/numba_backend/_common.py +++ b/sparse/numba_backend/_common.py @@ -1170,13 +1170,13 @@ def _parse_einsum_input(operands): Examples -------- The operand list is simplified to reduce printing: - >>> np.random.seed(123) - >>> a = np.random.rand(4, 4) - >>> b = np.random.rand(4, 4, 4) - >>> _parse_einsum_input(("...a,...a->...", a, b)) - ('za,xza', 'xz', [a, b]) # may vary - >>> _parse_einsum_input((a, [Ellipsis, 0], b, [Ellipsis, 0])) - ('za,xza', 'xz', [a, b]) # may vary + >>> rng = np.random.default_rng(42) + >>> a = rng.random((4, 4)) + >>> b = rng.random((4, 4, 4)) + >>> _parse_einsum_input(("...a,...a->...", a, b)) # doctest: +SKIP + ('za,xza', 'xz', [a, b]) + >>> _parse_einsum_input((a, [Ellipsis, 0], b, [Ellipsis, 0])) # doctest: +SKIP + ('za,xza', 'xz', [a, b]) """ if len(operands) == 0: @@ -2058,7 +2058,7 @@ def asarray(obj, /, *, dtype=None, format="coo", copy=False, device=None): >>> sparse.asarray(x, format="COO") """ - + format = format.lower() if format not in {"coo", "dok", "gcxs", "csc", "csr"}: raise ValueError(f"{format} format not supported.") @@ -2110,136 +2110,14 @@ def wrapper_func(*args, **kwargs): def all(x, /, *, axis=None, keepdims=False): - """ - Tests whether all input array elements evaluate to ``True`` along a specified axis. - - Parameters - ---------- - x: array - input array. - axis: Optional[Union[int, Tuple[int, ...]]] - axis or axes along which to perform a logical AND reduction. By default, a logical AND - reduction is performed over the entire array. - If a tuple of integers, logical AND reductions are performed over multiple axes. - A valid ``axis`` is an integer on the interval ``[-N, N)``, where ``N`` is the rank - (number of dimensions) of ``x``. If an ``axis`` is specified as a negative integer, - the function determines the axis along which to perform a reduction by counting backward - from the last dimension (where ``-1`` refers to the last dimension). If provided an invalid - ``axis``, the function raiseS an exception. Default: ``None``. - keepdims: bool - If ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions, - and, accordingly, the result is compatible with the input array. - Otherwise, if ``False``, the reduced axes (dimensions) are not included in the result. - Default: ``False``. - - Returns - ------- - out: array - if a logical AND reduction was performed over the entire array, the returned array is a - zero-dimensional array containing the test result; otherwise, the returned array is a - non-zero-dimensional array containing the test results. - The returned array has a data type of ``bool``. - - Special Cases - ------------- - - - Positive infinity, negative infinity, and NaN evaluate to ``True``. - - - If ``x`` has a complex floating-point data type, elements having a non-zero component - (real or imaginary) evaluate to ``True``. - - - If ``x`` is an empty array or the size of the axis (dimension) along which to evaluate elements - is zero, the test result is ``True``. - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) - >>> o = sparse.all(a, axis=1) - >>> o.todense() # doctest: +NORMALIZE_WHITESPACE - array([False, False]) - """ return x.all(axis=axis, keepdims=keepdims) def any(x, /, *, axis=None, keepdims=False): - """ - Tests whether any input array element evaluates to ``True`` along a specified axis. - - Parameters - ---------- - x: array - input array. - axis: Optional[Union[int, Tuple[int, ...]]] - axis or axes along which to perform a logical OR reduction. - By default, a logical OR reduction is performed over the entire array. - If a tuple of integers, logical OR reductions are performed over multiple axes. - A valid ``axis`` must be an integer on the interval ``[-N, N)``, where ``N`` is the rank (number of - dimensions) of ``x``. If an ``axis`` is specified as a negative integer, the function determines - the axis along which to perform a reduction by counting backward from the last dimension (where - ``-1`` refers to the last dimension). - If provided an invalid ``axis``, the function raises an exception. - Default: ``None``. - keepdims: bool - If ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions, - and, accordingly, the result must is compatible with the input array. Otherwise, if ``False``, - the reduced axes (dimensions) is not included in the result. - Default: ``False``. - - Returns - ------- - out: array - if a logical OR reduction was performed over the entire array, the returned array is a - zero-dimensional array containing the test result. - Otherwise, the returned array is a non-zero-dimensional array containing the test results. - The returned array is of type ``bool``. - - Special Cases - ------------- - - - Positive infinity, negative infinity, and NaN evaluate to ``True``. - - - If ``x`` has a complex floating-point data type, elements having a non-zero component - (real or imaginary) evaluate to ``True``. - - - If ``x`` is an empty array or the size of the axis (dimension) along which to evaluate elements - is zero, the test result is ``False``. - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) - >>> o = sparse.any(a, axis=1) - >>> o.todense() # doctest: +NORMALIZE_WHITESPACE - array([ True, True]) - """ return x.any(axis=axis, keepdims=keepdims) def permute_dims(x, /, axes=None): - """ - Permutes the axes (dimensions) of an array ``x``. - - Parameters - ---------- - x: array - input array. - axes: Tuple[int, ...] - tuple containing a permutation of ``(0, 1, ..., N-1)`` where ``N`` is the number of axes (dimensions) - of ``x``. - - Returns - ------- - out: array - an array containing the axes permutation. The returned array must have the same data type as ``x``. - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) - >>> o = sparse.permute_dims(a, axes=(1, 0)) - >>> o.todense() # doctest: +NORMALIZE_WHITESPACE - array([[0, 2], - [1, 0]]) - """ - return x.transpose(axes=axes) @@ -2282,454 +2160,38 @@ def max(x, /, *, axis=None, keepdims=False): def mean(x, /, *, axis=None, keepdims=False, dtype=None): - """ - Calculates the arithmetic mean of the input array ``x``. - - Parameters - ---------- - x: array - input array of a real-valued floating-point data type. - axis: Optional[Union[int, Tuple[int, ...]]] - axis or axes along which arithmetic means must be computed. - By default, the mean is computed over the entire array. - If a tuple of integers, arithmetic means are computed over multiple axes. Default: ``None``. - keepdims: bool - if ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions. - Accordingly, the result is compatible is the input array. - Otherwise, if ``False``, the reduced axes (dimensions) are not be included in the result. Default: ``False``. - - Returns - ------- - out: array - if the arithmetic mean was computed over the entire array, a zero-dimensional array with the arithmetic mean. - Otherwise, a non-zero-dimensional array containing the arithmetic means. - The returned array has the same data type as ``x``. - - Special Cases - ------------- - Let ``N`` equal the number of elements over which to compute the arithmetic mean. - If ``N`` is ``0``, the arithmetic mean is ``NaN``. - If ``x_i`` is ``NaN``, the arithmetic mean is ``NaN`` (i.e., ``NaN`` values propagate). - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) - >>> o = sparse.mean(a, axis=1) - >>> o.todense() - array([0.5, 1. ]) - """ - return x.mean(axis=axis, keepdims=keepdims, dtype=dtype) def min(x, /, *, axis=None, keepdims=False): - """ - Calculates the minimum value of the input array ``x``. - - Parameters - ---------- - x: array - input array. Should have a real-valued data type. - axis: Optional[Union[int, Tuple[int, ...]]] - axis or axes along which minimum values are computed. - By default, the minimum value must be computed over the entire array. - If a tuple of integers, minimum values must be computed over multiple axes. Default: ``None``. - keepdims: bool - If ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions. - Accordingly, the result must be compatible with the input array. - Otherwise, if ``False``, the reduced axes (dimensions) are not be included in the result. Default: ``False``. - - Returns - ------- - out: array - if the minimum value was computed over the entire array, a zero-dimensional array containing the minimum value. - Otherwise, a non-zero-dimensional array containing the minimum values. - The returned array must have the same data type as ``x``. - - Special Cases - ------------- - For floating-point operands, if ``x_i`` is ``NaN``, the minimum value is ``NaN`` (i.e., ``NaN`` values propagate). - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, -1], [-2, 0]])) - >>> o = sparse.min(a, axis=1) - >>> o.todense() - array([-1, -2]) - """ return x.min(axis=axis, keepdims=keepdims) def prod(x, /, *, axis=None, dtype=None, keepdims=False): - """ - Calculates the product of input array ``x`` elements. - - Parameters - ---------- - x: array - input array of a numeric data type. - axis: Optional[Union[int, Tuple[int, ...]]] - axis or axes along which products is computed. - By default, the product are computed over the entire array. - If a tuple of integers, products are computed over multiple axes. Default: ``None``. - - dtype: Optional[dtype] - data type of the returned array. - If ``None``, the returned array has the same data type as ``x``, unless ``x`` has an integer - data type supporting a smaller range of values than the default integer data type - (e.g., ``x`` has an ``int16`` or ``uint32`` data type and the default integer data type is ``int64``). - In those latter cases: - - - if ``x`` has a signed integer data type (e.g., ``int16``), the returned array has the - default integer data type. - - if ``x`` has an unsigned integer data type (e.g., ``uint16``), the returned array has an - unsigned integer data type having the same number of bits as the default integer data type - (e.g., if the default integer data type is ``int32``, the returned array must have a ``uint32`` data type). - - If the data type (either specified or resolved) differs from the data type of ``x``, the input array is - cast to the specified data type before computing the sum (rationale: the ``dtype`` keyword argument is - intended to help prevent overflows). Default: ``None``. - - keepdims: bool - if ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions. - Accordingly, the result are compatible with the input array. - Otherwise, if ``False``, the reduced axes (dimensions) are not included in the result. - Default: ``False``. - - Returns - ------- - out: array - if the product was computed over the entire array, a zero-dimensional array containing the product. - Otherwise, a non-zero-dimensional array containing the products. - The returned array has a data type as described by the ``dtype`` parameter above. - - Notes - ----- - - Special Cases - ------------- - Let ``N`` equal the number of elements over which to compute the product. - - - If ``N`` is ``0``, the product is `1` (i.e., the empty product). - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 2], [-1, 1]])) - >>> o = sparse.prod(a, axis=1) - >>> o.todense() - array([ 0, -1]) - """ return x.prod(axis=axis, keepdims=keepdims, dtype=dtype) def std(x, /, *, axis=None, correction=0.0, keepdims=False): - """ - Calculates the standard deviation of the input array ``x``. - - Parameters - ---------- - x: array - input array of a real-valued floating-point data type. - axis: Optional[Union[int, Tuple[int, ...]]] - axis or axes along which standard deviations are computed. - By default, the standard deviation is computed over the entire array. - If a tuple of integers, standard deviations are computed over multiple axes. - Default: ``None``. - correction: Union[int, float] - degrees of freedom adjustment. - Setting this parameter to a value other than ``0`` has the effect of adjusting the divisor - during the calculation of the standard deviation according to ``N-c`` where ``N`` corresponds - to the total number of elements over which the standard deviation is computed - and ``c`` corresponds to the provided degrees of freedom adjustment. When computing the - standard deviation of a population, setting this parameter to ``0`` is the standard choice - (i.e., the provided array contains data constituting an entire population). When computing - the corrected sample standard deviation, setting this parameter to ``1`` is the standard - choice (i.e., the provided array contains data sampled from a larger population; this is - commonly referred to as Bessel's correction). Default: ``0``. - keepdims: bool - if ``True``, the reduced axes (dimensions) are included in the result as singleton - dimensions, and, accordingly, the result must be compatible with the input array. - Otherwise, if ``False``, the reduced axes (dimensions) must not - be included in the result. Default: ``False``. - - Returns - ------- - out: array - if the standard deviation was computed over the entire array, a zero-dimensional array containing - the standard deviation; otherwise, a non-zero-dimensional array containing the standard deviations. - The returned array has the same data type as ``x``. - - Special Cases - ------------- - Let ``N`` equal the number of elements over which to compute the standard deviation. - - - If ``N - correction`` is less than or equal to ``0``, the standard deviation is ``NaN``. - - If ``x_i`` is ``NaN``, the standard deviation is ``NaN`` (i.e., ``NaN`` values propagate). - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 2], [-1, 1]])) - >>> o = sparse.std(a, axis=1) - >>> o.todense() - array([1., 1.]) - """ return x.std(axis=axis, ddof=correction, keepdims=keepdims) def sum(x, /, *, axis=None, dtype=None, keepdims=False): - """ - Calculates the sum of the input array ``x``. - - Parameters - ---------- - x: array - input array of a numeric data type. - axis: Optional[Union[int, Tuple[int, ...]]] - axis or axes along which sums are computed. - By default, the sum is computed over the entire array. - If a tuple of integers, sums must are computed over multiple axes. Default: ``None``. - - dtype: Optional[dtype] - data type of the returned array. - If ``None``, the returned array has the same data type as ``x``, unless ``x`` has an integer data type - supporting a smaller range of values than the default integer data type (e.g., ``x`` has an ``int16`` - or ``uint32`` data type and the default integer data type is ``int64``). In those latter cases: - - - if ``x`` has a signed integer data type (e.g., ``int16``), the returned array has the default integer - data type. - - if ``x`` has an unsigned integer data type (e.g., ``uint16``), the returned array has an unsigned integer - data type having the same number of bits as the default integer data type (e.g., if the default integer - data type is ``int32``, the returned array must have a ``uint32`` data type). - - If the data type (either specified or resolved) differs from the data type of ``x``, the input array is cast to - the specified data type before computing the sum. - Rationale: the ``dtype`` keyword argument is intended to help prevent overflows. Default: ``None``. - keepdims: bool - If ``True``, the reduced axes (dimensions) are included in the result as singleton dimensions. - Accordingly, the result is compatible with the input array. - Otherwise, if ``False``, the reduced axes (dimensions) are not included in the result. Default: ``False``. - - Returns - ------- - out: array - if the sum was computed over the entire array, a zero-dimensional array containing the sum. - Otherwise, an array containing the sums. - The returned array has the data type as described by the ``dtype`` parameter above. - - Special Cases - ------------- - Let ``N`` equal the number of elements over which to compute the sum. - - - If ``N`` is ``0``, the sum is ``0`` (i.e., the empty sum). - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) - >>> o = sparse.sum(a, axis=1) - >>> o.todense() - array([1, 2]) - """ return x.sum(axis=axis, keepdims=keepdims, dtype=dtype) def var(x, /, *, axis=None, correction=0.0, keepdims=False): - """ - Calculates the variance of the input array ``x``. - - Parameters - ---------- - x: array - input array of a real-valued floating-point data type. - axis: Optional[Union[int, Tuple[int, ...]]] - axis or axes along which variances are computed. - By default, the variance is computed over the entire array. - If a tuple of integers, variances are computed over multiple axes. Default: ``None``. - correction: Union[int, float] - degrees of freedom adjustment. Setting this parameter to a value other than ``0`` - has the effect of adjusting the divisor during the calculation of the variance according to ``N-c`` - where ``N`` corresponds to the total number of elements over which the variance is computed and ``c`` - corresponds to the provided degrees of freedom adjustment. - When computing the variance of a population, setting this parameter to ``0`` is the standard choice - (i.e., the provided array contains data constituting an entire population). - When computing the unbiased sample variance, setting this parameter to ``1`` is the standard choice - (i.e., the provided array contains data sampled from a larger population; this is commonly referred - to as Bessel's correction). Default: ``0``. - keepdims: bool - if ``True``, the reduced axes are included in the result as singleton dimensions, and, - accordingly, the result is compatible with the input array. - Otherwise, if ``False``, the reduced axes (dimensions) are not included in the result. Default: ``False``. - - Returns - ------- - out: array - if the variance was computed over the entire array, a zero-dimensional array containing the variance; - otherwise, a non-zero-dimensional array containing the variances. - The returned array must have the same data type as ``x``. - - Special Cases - ------------- - Let ``N`` equal the number of elements over which to compute the variance. - - - If ``N - correction`` is less than or equal to ``0``, the variance is ``NaN``. - - If ``x_i`` is ``NaN``, the variance is ``NaN`` (i.e., ``NaN`` values propagate). - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 2], [-1, 1]])) - >>> o = sparse.var(a, axis=1) - >>> o.todense() - array([1., 1.]) - """ return x.var(axis=axis, ddof=correction, keepdims=keepdims) def abs(x, /): - """ - Calculates the absolute value for each element ``x_i`` of the input array ``x``. - - For real-valued input arrays, the element-wise result has the same magnitude as the respective - element in ``x`` but has positive sign. - - For complex floating-point operands, the complex absolute value is known as the norm, modulus, or - magnitude and, for a complex number :math:`z = a + bj` is computed as - - $$ - operatorname{abs}(z) = sqrt{a^2 + b^2} - $$ - - Parameters - ---------- - x: array - input array of a numeric data type. - - Returns - ------- - out: array - an array containing the absolute value of each element in ``x``. - If ``x`` has a real-valued data type, the returned array has the same data type as ``x``. - If ``x`` has a complex floating-point data type, the returned array has a real-valued - floating-point data type whose precision matches the precision of ``x`` - (e.g., if ``x`` is ``complex128``, then the returned array must has a ``float64`` data type). - - Special Cases - ------------- - For real-valued floating-point operands, - - - If ``x_i`` is ``NaN``, the result is ``NaN``. - - If ``x_i`` is ``-0``, the result is ``+0``. - - If ``x_i`` is ``-infinity``, the result is ``+infinity``. - - For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and - - - If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is any value (including ``NaN``), - the result is ``+infinity``. - - If ``a`` is any value (including ``NaN``) and ``b`` is either ``+infinity`` or ``-infinity``, - the result is ``+infinity``. - - If ``a`` is either ``+0`` or ``-0``, the result is equal to ``abs(b)``. - - If ``b`` is either ``+0`` or ``-0``, the result is equal to ``abs(a)``. - - If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN``. - - If ``a`` is a finite number and ``b`` is ``NaN``, the result is ``NaN``. - - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN``. - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, -1], [-2, 0]])) - >>> o = sparse.abs(a) - >>> o.todense() - array([[0, 1], - [2, 0]]) - """ - return x.__abs__() def reshape(x, /, shape, *, copy=None): - """ - Reshapes an array without changing its data. - - Parameters - ---------- - x: array - input array to reshape. - shape: Tuple[int, ...] - a new shape compatible with the original shape. One shape dimension is allowed to be ``-1``. - When a shape dimension is ``-1``, the corresponding output array shape dimension must be inferred - from the length of the array and the remaining dimensions. - copy: Optional[bool] - whether or not to copy the input array. - If ``True``, the function always copies. - If ``False``, the function must never copies. - If ``None``, the function avoids copying, if possible. - Default: ``None``. - - Returns - ------- - out: array - an output array having the same data type and elements as ``x``. - - Raises - ------ - ValueError - If ``copy=False`` and a copy would be necessary, a ``ValueError`` - will be raised. - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) - >>> o = sparse.reshape(a, shape=(1, 4)) - >>> o.todense() - array([[0, 1, 2, 0]]) - """ return x.reshape(shape=shape) def astype(x, dtype, /, *, copy=True): - """ - Copies an array to a specified data type irrespective of type-promotion rules. - - Parameters - ---------- - x: array - array to cast. - dtype: dtype - desired data type. - copy: bool - specifies whether to copy an array when the specified ``dtype`` matches the data type - of the input array ``x``. If ``True``, a newly allocated array is always returned. - If ``False`` and the specified ``dtype`` matches the data type of the input array, - the input array is returned; otherwise, a newly allocated array is returned. - Default: ``True``. - - Notes - ----- - - - When casting a boolean input array to a real-valued data type, a value of ``True`` is cast - to a real-valued number equal to ``1``, and a value of ``False`` must cast to a real-valued - number equal to ``0``. - - - When casting a boolean input array to a complex floating-point data type, a value of ``True`` - is cast to a complex number equal to ``1 + 0j``, and a value of ``False`` is cast to a complex - number equal to ``0 + 0j``. - - - When casting a real-valued input array to ``bool``, a value of ``0`` is cast to ``False``, - and a non-zero value is cast to ``True``. - - - When casting a complex floating-point array to ``bool``, a value of ``0 + 0j`` is cast - to ``False``, and all other values are cast to ``True``. - - Returns - ------- - out: array - an array having the specified data type. The returned array has the same shape as ``x``. - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) - >>> o = sparse.astype(a, "float32") - >>> o.todense() # doctest: +NORMALIZE_WHITESPACE - array([[0., 1.], - [2., 0.]], dtype=float32) - """ return x.astype(dtype, copy=copy) @@ -2754,112 +2216,15 @@ def squeeze(x, /, axis=None): @_support_numpy def broadcast_to(x, /, shape): - """ - Broadcasts an array to a specified shape. - - Parameters - ---------- - x: array - array to broadcast. - shape: Tuple[int, ...] - array shape. Must be compatible with ``x``. - If the array is incompatible with the specified shape, the function raises an exception. - - Returns - ------- - out: array - an array having a specified shape and having the same data type as ``x``. - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) - >>> o = sparse.broadcast_to(a, shape=(1, 2, 2)) - >>> o.todense() # doctest: +NORMALIZE_WHITESPACE - array([[[0, 1], - [2, 0]]]) - """ return x.broadcast_to(shape) def broadcast_arrays(*arrays): - """ - Broadcasts one or more arrays against one another. - - Parameters - ---------- - arrays: array - an arbitrary number of to-be broadcasted arrays. - - Returns - ------- - out: List[array] - a list of broadcasted arrays. Each array has the same shape. - Each array has the same dtype as its corresponding input array. - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1]])) - >>> b = sparse.COO.from_numpy(np.array([[0], [2]])) - >>> oa, ob = sparse.broadcast_arrays(a, b) - >>> oa.todense() # doctest: +NORMALIZE_WHITESPACE - array([[0, 1], - [0, 1]]) - >>> ob.todense() # doctest: +NORMALIZE_WHITESPACE - array([[0, 0], - [2, 2]]) - """ - shape = np.broadcast_shapes(*[a.shape for a in arrays]) return [a.broadcast_to(shape) for a in arrays] def equal(x1, x2, /): - """ - Computes the truth value of ``x1_i == x2_i`` for each element ``x1_i`` of the input array ``x1`` - with the respective element ``x2_i`` of the input array ``x2``. - - Parameters - ---------- - x1: array - first input array. May have any data type. - x2: array - second input array. Must be compatible with ``x1``. May have any data type. - - Returns - ------- - out: array - an array containing the element-wise results. The returned array is of data type of ``bool``. - - Special Cases - ------------- - - For real-valued floating-point operands, - - - If ``x1_i`` is ``NaN`` or ``x2_i`` is ``NaN``, the result is ``False``. - - If ``x1_i`` is ``+infinity`` and ``x2_i`` is ``+infinity``, the result is ``True``. - - If ``x1_i`` is ``-infinity`` and ``x2_i`` is ``-infinity``, the result is ``True``. - - If ``x1_i`` is ``-0`` and ``x2_i`` is either ``+0`` or ``-0``, the result is ``True``. - - If ``x1_i`` is ``+0`` and ``x2_i`` is either ``+0`` or ``-0``, the result is ``True``. - - If ``x1_i`` is a finite number, ``x2_i`` is a finite number, and ``x1_i`` equals ``x2_i``, the result is ``True``. - - In the remaining cases, the result is ``False``. - - For complex floating-point operands, let ``a = real(x1_i)``, ``b = imag(x1_i)``, ``c = real(x2_i)``, - ``d = imag(x2_i)``, and - - - If ``a``, ``b``, ``c``, or ``d`` is ``NaN``, the result is ``False``. - - In the remaining cases, the result is the logical AND of the equality comparison between the real values ``a`` - and ``c`` (real components) and between the real values ``b`` and ``d`` (imaginary components), as described - above for real-valued floating-point operands (i.e., ``a == c AND b == d``). - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) - >>> b = sparse.COO.from_numpy(np.array([[0, 1], [1, 0]])) - >>> o = sparse.equal(a, b) # doctest: +SKIP - >>> o.todense() # doctest: +SKIP - array([[ True, True], - [ False, True]]) - """ return x1 == x2 @@ -2870,169 +2235,23 @@ def round(x, /, decimals=0, out=None): @_support_numpy def isinf(x, /): - """ - Tests each element ``x_i`` of the input array ``x`` to determine if equal to positive or negative infinity. - - Parameters - ---------- - x: array - input array of a numeric data type. - - Returns - ------- - out: array - an array containing test results. The returned array has a data type of ``bool``. - - Special Cases - ------------- - - For real-valued floating-point operands, - - - If ``x_i`` is either ``+infinity`` or ``-infinity``, the result is ``True``. - - In the remaining cases, the result is ``False``. - - For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and - - - If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is any value (including ``NaN``), the result - is ``True``. - - If ``a`` is either a finite number or ``NaN`` and ``b`` is either ``+infinity`` or ``-infinity``, the result - is ``True``. - - In the remaining cases, the result is ``False``. - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, np.inf]])) - >>> o = sparse.isinf(a) # doctest: +SKIP - >>> o.todense() # doctest: +SKIP - array([[False, False], - [False, True]]) - """ return x.isinf() @_support_numpy def isnan(x, /): - """ - Tests each element ``x_i`` of the input array ``x`` to determine whether the element is ``NaN``. - - Parameters - ---------- - x: array - input array with a numeric data type. - - Returns - ------- - out: array - an array containing test results. The returned array has data type ``bool``. - - Notes - ----- - - For real-valued floating-point operands, - - - If ``x_i`` is ``NaN``, the result is ``True``. - - In the remaining cases, the result is ``False``. - - For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and - - - If ``a`` or ``b`` is ``NaN``, the result is ``True``. - - In the remaining cases, the result is ``False``. - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, np.nan]])) - >>> o = sparse.isnan(a) - >>> o.todense() # doctest: +NORMALIZE_WHITESPACE - array([[False, False], - [False, True]]) - """ - return x.isnan() def nonzero(x, /): - """ - Returns the indices of the array elements which are non-zero. - - If ``x`` has a complex floating-point data type, non-zero elements are those elements having at least - one component (real or imaginary) which is non-zero. - - If ``x`` has a boolean data type, non-zero elements are those elements which are equal to ``True``. - - Parameters - ---------- - x: array - input array having a positive rank. - If ``x`` is zero-dimensional, the function raises an exception. - - Returns - ------- - out: Tuple[array, ...] - a tuple of ``k`` arrays, one for each dimension of ``x`` and each of size ``n`` (where ``n`` is - the total number of non-zero elements), containing the indices of the non-zero elements in that - dimension. The indices must are returned in row-major, C-style order. - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0, 1], [2, 0]])) - >>> o = sparse.nonzero(a) - >>> o - (array([0, 1]), array([1, 0])) - """ return x.nonzero() def imag(x, /): - """ - Returns the imaginary component of a complex number for each element ``x_i`` of the input array ``x``. - - Parameters - ---------- - x: array - input array of a complex floating-point data type. - - Returns - ------- - out: array - an array containing the element-wise results. - The returned array has a floating-point data type with the same floating-point precision as ``x`` - (e.g., if ``x`` is ``complex64``, the returned array has the floating-point data type ``float32``). - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0 + 1j, 2 + 0j], [0 + 0j, 3 + 1j]])) - >>> o = sparse.imag(a) - >>> o.todense() # doctest: +NORMALIZE_WHITESPACE - array([[1., 0.], - [0., 1.]]) - """ return x.imag def real(x, /): - """ - Returns the real component of a complex number for each element ``x_i`` of the input array ``x``. - - Parameters - ---------- - x: array - input array of a complex floating-point data type. - - Returns - ------- - out: array - an array containing the element-wise results. - The returned array has a floating-point data type with the same floating-point precision as ``x`` - (e.g., if ``x`` is ``complex64``, the returned array has the floating-point data type ``float32``). - - Examples - -------- - >>> a = sparse.COO.from_numpy(np.array([[0 + 1j, 2 + 0j], [0 + 0j, 3 + 1j]])) - >>> o = sparse.real(a) - >>> o.todense() # doctest: +NORMALIZE_WHITESPACE - array([[0., 2.], - [0., 3.]]) - """ return x.real diff --git a/sparse/numba_backend/_compressed/compressed.py b/sparse/numba_backend/_compressed/compressed.py index 85bce095..380f539b 100644 --- a/sparse/numba_backend/_compressed/compressed.py +++ b/sparse/numba_backend/_compressed/compressed.py @@ -819,7 +819,7 @@ def _prune(self): -------- >>> coords = np.array([[0, 1, 2, 3]]) >>> data = np.array([1, 0, 1, 2]) - >>> s = COO(coords, data).asformat("gcxs") + >>> s = COO(coords, data, shape=(4,)).asformat("gcxs") >>> s._prune() >>> s.nnz 3 diff --git a/sparse/numba_backend/_coo/common.py b/sparse/numba_backend/_coo/common.py index 9ef5f5a9..9b186dfc 100644 --- a/sparse/numba_backend/_coo/common.py +++ b/sparse/numba_backend/_coo/common.py @@ -901,7 +901,7 @@ def diagonalize(a, axis=0): >>> a = sparse.random((3, 3, 3, 3, 3), density=0.3) >>> a_diag = sparse.diagonalize(a, axis=2) >>> (sparse.diagonal(a_diag, axis1=2, axis2=5) == a.transpose([0, 1, 3, 4, 2])).all() - True + np.True_ Returns ------- @@ -944,7 +944,7 @@ def isposinf(x, out=None): -------- [`numpy.isposinf`][] : The NumPy equivalent """ - from .core import elemwise + from sparse import elemwise return elemwise(lambda x, out=None, dtype=None: np.isposinf(x, out=out), x, out=out) @@ -971,7 +971,7 @@ def isneginf(x, out=None): -------- [`numpy.isneginf`][] : The NumPy equivalent """ - from .core import elemwise + from sparse import elemwise return elemwise(lambda x, out=None, dtype=None: np.isneginf(x, out=out), x, out=out) @@ -1234,7 +1234,7 @@ def unique_values(x, /): >>> import sparse >>> x = sparse.COO.from_numpy([1, 0, 2, 1, 2, -3]) >>> sparse.unique_values(x) - array([-3, 0, 1, 2]) + array([-3, 0, 1, 2]) """ x = _validate_coo_input(x) @@ -1279,9 +1279,9 @@ def sort(x, /, *, axis=-1, descending=False, stable=False): >>> import sparse >>> x = sparse.COO.from_numpy([1, 0, 2, 0, 2, -3]) >>> sparse.sort(x).todense() - array([-3, 0, 0, 1, 2, 2]) + array([-3, 0, 0, 1, 2, 2]) >>> sparse.sort(x, descending=True).todense() - array([ 2, 2, 1, 0, 0, -3]) + array([ 2, 2, 1, 0, 0, -3]) """ from .._common import moveaxis diff --git a/sparse/numba_backend/_coo/core.py b/sparse/numba_backend/_coo/core.py index 2b4b5a82..2db83fde 100644 --- a/sparse/numba_backend/_coo/core.py +++ b/sparse/numba_backend/_coo/core.py @@ -156,7 +156,7 @@ class COO(SparseArray, NDArrayOperatorsMixin): # lgtm [py/missing-equals] >>> rows = [0, 1, 2, 3, 4] >>> cols = [0, 0, 0, 1, 1] >>> data = [10, 20, 30, 40, 50] - >>> z = COO((data, (rows, cols))) + >>> z = COO((data, (rows, cols)), shape=(5, 2)) >>> z.todense() # doctest: +NORMALIZE_WHITESPACE array([[10, 0], [20, 0], @@ -168,10 +168,10 @@ class COO(SparseArray, NDArrayOperatorsMixin): # lgtm [py/missing-equals] indices imply summation: >>> d = {(0, 0, 0): 1, (1, 2, 3): 2, (1, 1, 0): 3} - >>> COO(d) + >>> COO(d, shape=(2, 3, 4)) >>> L = [((0, 0), 1), ((1, 1), 2), ((0, 0), 3)] - >>> COO(L).todense() # doctest: +NORMALIZE_WHITESPACE + >>> COO(L, shape=(2, 2)).todense() # doctest: +NORMALIZE_WHITESPACE array([[4, 0], [0, 2]]) @@ -440,6 +440,7 @@ def from_scipy_sparse(cls, x, /, *, fill_value=None): Examples -------- + >>> import scipy.sparse >>> x = scipy.sparse.rand(6, 3, density=0.2) >>> s = COO.from_scipy_sparse(x) >>> np.array_equal(x.todense(), s.todense()) @@ -459,7 +460,7 @@ def from_scipy_sparse(cls, x, /, *, fill_value=None): ) @classmethod - def from_iter(cls, x, shape=None, fill_value=None, dtype=None): + def from_iter(cls, x, shape, fill_value=None, dtype=None): """ Converts an iterable in certain formats to a [`sparse.COO`][] array. See examples for details. @@ -468,7 +469,7 @@ def from_iter(cls, x, shape=None, fill_value=None, dtype=None): ---------- x : Iterable or Iterator The iterable to convert to [`sparse.COO`][]. - shape : tuple[int], optional + shape : tuple[int] The shape of the array. fill_value : scalar The fill value for this array. @@ -486,7 +487,7 @@ def from_iter(cls, x, shape=None, fill_value=None, dtype=None): Here, the first part represents the coordinate and the second part represents the value. >>> x = [((0, 0), 1), ((1, 1), 1)] - >>> s = COO.from_iter(x) + >>> s = COO.from_iter(x, shape=(2, 2)) >>> s.todense() array([[1, 0], [0, 1]]) @@ -494,7 +495,7 @@ def from_iter(cls, x, shape=None, fill_value=None, dtype=None): You can also have a similar format with a dictionary. >>> x = {(0, 0): 1, (1, 1): 1} - >>> s = COO.from_iter(x) + >>> s = COO.from_iter(x, shape=(2, 2)) >>> s.todense() array([[1, 0], [0, 1]]) @@ -502,7 +503,7 @@ def from_iter(cls, x, shape=None, fill_value=None, dtype=None): The third supported format is ``(data, (..., row, col))``. >>> x = ([1, 1], ([0, 1], [0, 1])) - >>> s = COO.from_iter(x) + >>> s = COO.from_iter(x, shape=(2, 2)) >>> s.todense() array([[1, 0], [0, 1]]) @@ -510,7 +511,7 @@ def from_iter(cls, x, shape=None, fill_value=None, dtype=None): You can also pass in a [`collections.abc.Iterator`][] object. >>> x = [((0, 0), 1), ((1, 1), 1)].__iter__() - >>> s = COO.from_iter(x) + >>> s = COO.from_iter(x, shape=(2, 2)) >>> s.todense() array([[1, 0], [0, 1]]) @@ -1293,7 +1294,7 @@ def _sort_indices(self): -------- >>> coords = np.array([[1, 2, 0]], dtype=np.uint8) >>> data = np.array([4, 1, 3], dtype=np.uint8) - >>> s = COO(coords, data) + >>> s = COO(coords, data, shape=(3,)) >>> s._sort_indices() >>> s.coords # doctest: +NORMALIZE_WHITESPACE array([[0, 1, 2]], dtype=uint8) @@ -1321,7 +1322,7 @@ def _sum_duplicates(self): -------- >>> coords = np.array([[0, 1, 1, 2]], dtype=np.uint8) >>> data = np.array([6, 5, 2, 2], dtype=np.uint8) - >>> s = COO(coords, data) + >>> s = COO(coords, data, shape=(3,)) >>> s._sum_duplicates() >>> s.coords # doctest: +NORMALIZE_WHITESPACE array([[0, 1, 2]], dtype=uint8) @@ -1354,7 +1355,7 @@ def _prune(self): -------- >>> coords = np.array([[0, 1, 2, 3]]) >>> data = np.array([1, 0, 1, 2]) - >>> s = COO(coords, data) + >>> s = COO(coords, data, shape=(4,)) >>> s._prune() >>> s.nnz 3 diff --git a/sparse/numba_backend/_coo/indexing.py b/sparse/numba_backend/_coo/indexing.py index 6760e98f..5373da06 100644 --- a/sparse/numba_backend/_coo/indexing.py +++ b/sparse/numba_backend/_coo/indexing.py @@ -524,9 +524,9 @@ def _get_mask_pairs(starts_old, stops_old, c, idx): # pragma: no cover -------- >>> c = np.array([1, 2, 1, 2, 1, 1, 2, 2]) >>> starts_old = numba.typed.List() - ... starts_old.append(4) + >>> starts_old.append(4) >>> stops_old = numba.typed.List() - ... stops_old.append(8) + >>> stops_old.append(8) >>> idx = np.array([1, 2, 1]) >>> _get_mask_pairs(starts_old, stops_old, c, idx) (ListType[int64]([4]), ListType[int64]([6]), 2) @@ -575,9 +575,9 @@ def _filter_pairs(starts, stops, coords, indices): # pragma: no cover -------- >>> import numpy as np >>> starts = numba.typed.List() - ... starts.append(2) + >>> starts.append(2) >>> stops = numba.typed.List() - ... stops.append(7) + >>> stops.append(7) >>> coords = np.array([[0, 1, 2, 3, 4, 5, 6, 7]]) >>> indices = np.array([[2, 8, 2]]) # Start, stop, step pairs >>> _filter_pairs(starts, stops, coords, indices) @@ -627,11 +627,11 @@ def _join_adjacent_pairs(starts_old, stops_old): # pragma: no cover Examples -------- >>> starts = numba.typed.List() - ... starts.append(2) - ... starts.append(5) + >>> starts.append(2) + >>> starts.append(5) >>> stops = numba.typed.List() - ... stops.append(5) - ... stops.append(7) + >>> stops.append(5) + >>> stops.append(7) >>> _join_adjacent_pairs(starts, stops) (ListType[int64]([2]), ListType[int64]([7])) """ diff --git a/sparse/numba_backend/_dok.py b/sparse/numba_backend/_dok.py index 9c4e601d..4cfed3bc 100644 --- a/sparse/numba_backend/_dok.py +++ b/sparse/numba_backend/_dok.py @@ -149,6 +149,7 @@ def from_scipy_sparse(cls, x, /, *, fill_value=None): Examples -------- + >>> import scipy.sparse >>> x = scipy.sparse.rand(6, 3, density=0.2) >>> s = DOK.from_scipy_sparse(x) >>> np.array_equal(x.todense(), s.todense()) diff --git a/sparse/numba_backend/_sparse_array.py b/sparse/numba_backend/_sparse_array.py index 7f47c6eb..13180521 100644 --- a/sparse/numba_backend/_sparse_array.py +++ b/sparse/numba_backend/_sparse_array.py @@ -691,7 +691,7 @@ def mean(self, axis=None, keepdims=False, dtype=None, out=None): mean along all axes. >>> s.mean() - 0.5 + np.float64(0.5) """ if axis is None: @@ -771,7 +771,7 @@ def var(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False): variance along all axes. >>> s.var() - 0.5 + np.float64(0.5) """ axis = normalize_axis(axis, self.ndim) diff --git a/sparse/numba_backend/_utils.py b/sparse/numba_backend/_utils.py index 554cb250..ce5fc29d 100644 --- a/sparse/numba_backend/_utils.py +++ b/sparse/numba_backend/_utils.py @@ -267,19 +267,18 @@ def random( Examples -------- - >>> from sparse import random >>> from scipy import stats - >>> rvs = lambda x: stats.poisson(25, loc=10).rvs(x, random_state=np.random.RandomState(1)) - >>> s = random((2, 3, 4), density=0.25, random_state=np.random.RandomState(1), data_rvs=rvs) - >>> s.todense() # doctest: +NORMALIZE_WHITESPACE - array([[[ 0, 0, 0, 0], - [34, 0, 29, 30], + >>> rng = np.random.default_rng(42) + >>> rvs = lambda x: stats.poisson(25, loc=10).rvs(x, random_state=rng) + >>> s = sparse.random((2, 3, 4), density=0.25, random_state=rng, data_rvs=rvs) + >>> s.todense() + array([[[39, 0, 0, 0], + [28, 33, 0, 37], [ 0, 0, 0, 0]], - [[33, 0, 0, 34], - [34, 0, 0, 0], - [ 0, 0, 0, 0]]]) - + [[ 0, 0, 0, 0], + [ 0, 0, 34, 0], + [ 0, 0, 0, 36]]]) """ # Copied, in large part, from scipy.sparse.random # See https://github.com/scipy/scipy/blob/main/LICENSE.txt @@ -422,15 +421,15 @@ def equivalent(x, y, /, loose=False): Examples -------- >>> equivalent(1, 1) - True + np.True_ >>> equivalent(np.nan, np.nan + 1) - True + np.True_ >>> equivalent(1, 2) - False + np.False_ >>> equivalent(np.inf, np.inf) - True - >>> equivalent(np.PZERO, np.NZERO) - False + np.True_ + >>> equivalent(np.float64(0.0), np.float64(-0.0)) + np.False_ """ x = np.asarray(x) y = np.asarray(y) diff --git a/sparse/numba_backend/tests/__init__.py b/sparse/numba_backend/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/sparse/numba_backend/tests/test_coo.py b/sparse/numba_backend/tests/test_coo.py index c929fff3..58df49d9 100644 --- a/sparse/numba_backend/tests/test_coo.py +++ b/sparse/numba_backend/tests/test_coo.py @@ -1025,11 +1025,14 @@ def test_invalid_attrs_error(): def test_invalid_iterable_error(): with pytest.raises(ValueError): x = [(3, 4, 5)] - COO.from_iter(x) + COO.from_iter(x, shape=(6,)) with pytest.raises(ValueError): x = [((2.3, 4.5), 3.2)] - COO.from_iter(x) + COO.from_iter(x, shape=(5,)) + + with pytest.raises(TypeError): + COO.from_iter({(1, 1): 1}) def test_prod_along_axis():