Repository: scipy/scipy
File: scipy/stats/_multivariate.py (Python)

Code before:
        Array of indices to marginalize
    """
    dims = np.copy(dimensions)
    dims = np.atleast_1d(dims)

    if len(dims) == 0:
        msg = ("Cannot marginalize all dimensions.")
        raise ValueError(msg)

    if not np.issubdtype(dims.dtype, np.integer):
        msg = ("Elements of `dimensions` must be integers - the indices "
                "of the marginal variables being retained.")
        raise ValueError(msg)

    original_dims = np.copy(dims)

    dims[dims < 0] = multivariate_dims + dims[dims < 0]

    if len(np.unique(dims)) != len(dims):
        msg = ("All elements of `dimensions` must be unique.")
        raise ValueError(msg)

    i_invalid = (dims < 0) | (dims >= multivariate_dims)
    if np.any(i_invalid):
        msg = (f"Dimensions {original_dims[i_invalid]} are invalid "
                f"for a distribution in {multivariate_dims} dimensions.")
        raise ValueError(msg)

    return dims


class _PSD:
    """
    Compute coordinated functions of a symmetric positive semidefinite matrix.

    This class addresses two issues.  Firstly it allows the pseudoinverse,
    the logarithm of the pseudo-determinant, and the rank of the matrix
    to be computed using one call to eigh instead of three.
    Secondly it allows these functions to be computed in a way
    that gives mutually compatible results.
    All of the functions are computed with a common understanding as to
    which of the eigenvalues are to be considered negligibly small.
    The functions are designed to coordinate with scipy.linalg.pinvh()
    but not necessarily with np.linalg.det() or with np.linalg.matrix_rank().

    Parameters
    ----------
    M : array_like
        Symmetric positive semidefinite matrix (2-D).
    cond, rcond : float, optional
        Cutoff for small eigenvalues.

Review comment (suggestion):
nitpick:

```suggestion
        msg = (f"Dimensions {original_dims[i_invalid]} are invalid "
               f"for a distribution in {multivariate_dims} dimensions.")
```

Code after:
    """
    dims = np.copy(dimensions)
    dims = np.atleast_1d(dims)

    if len(dims) == 0:
        msg = "Cannot marginalize all dimensions."
        raise ValueError(msg)

    if not np.issubdtype(dims.dtype, np.integer):
        msg = ("Elements of `dimensions` must be integers - the indices "
               "of the marginal variables being retained.")
        raise ValueError(msg)

    original_dims = np.copy(dims)

    dims[dims < 0] += multivariate_dims

    if len(np.unique(dims)) != len(dims):
        msg = "All elements of `dimensions` must be unique."
        raise ValueError(msg)

    i_invalid = (dims < 0) | (dims >= multivariate_dims)
    if np.any(i_invalid):
        msg = (f"Dimensions {original_dims[i_invalid]} are invalid "
               f"for a distribution in {multivariate_dims} dimensions.")
        raise ValueError(msg)

    return dims


class _PSD:
    """
    Compute coordinated functions of a symmetric positive semidefinite matrix.

    This class addresses two issues.  Firstly it allows the pseudoinverse,
    the logarithm of the pseudo-determinant, and the rank of the matrix
    to be computed using one call to eigh instead of three.
    Secondly it allows these functions to be computed in a way
    that gives mutually compatible results.
    All of the functions are computed with a common understanding as to
    which of the eigenvalues are to be considered negligibly small.
    The functions are designed to coordinate with scipy.linalg.pinvh()
    but not necessarily with np.linalg.det() or with np.linalg.matrix_rank().

    Parameters
    ----------
    M : array_like
        Symmetric positive semidefinite matrix (2-D).
    cond, rcond : float, optional
        Cutoff for small eigenvalues.
        Singular values smaller than rcond * largest_eigenvalue are