Given a player's payoff matrix `payoff_matrix`, an array `own_supp`
    of this player's actions, and an array `opp_supp` of the opponent's
    actions, each of length k, compute the opponent's mixed action whose
    support equals `opp_supp` and for which the player is indifferent
    among the actions in `own_supp`, if any such exists. Return `True`
    if such a mixed action exists and actions in `own_supp` are indeed
    best responses to it, in which case the outcome is stored in `out`;
    `False` otherwise. Array `A` is used in intermediate steps.

    Parameters
    ----------
    payoff_matrix : ndarray(ndim=2)
        The player's payoff matrix, of shape (m, n).

    own_supp : ndarray(int, ndim=1)
        Array containing the player's action indices, of length k.

    opp_supp : ndarray(int, ndim=1)
        Array containing the opponent's action indices, of length k.

    A : ndarray(float, ndim=2)
        Array used in intermediate steps, of shape (k+1, k+1).

    out : ndarray(float, ndim=1)
        Array of length k+1 to store the k nonzero values of the desired
        mixed action in `out[:-1]` (and the payoff value in `out[-1]`).

    Returns
    -------
    bool
        `True` if a desired mixed action exists and `False` otherwise.

def _indiff_mixed_action(payoff_matrix, own_supp, opp_supp, A, out):
    """
    Given a player's payoff matrix `payoff_matrix`, an array `own_supp`
    of this player's actions, and an array `opp_supp` of the opponent's
    actions, each of length k, compute the opponent's mixed action whose
    support equals `opp_supp` and for which the player is indifferent
    among the actions in `own_supp`, if any such exists. Return `True`
    if such a mixed action exists and actions in `own_supp` are indeed
    best responses to it, in which case the outcome is stored in `out`;
    `False` otherwise. Array `A` is used in intermediate steps.

    Parameters
    ----------
    payoff_matrix : ndarray(ndim=2)
        The player's payoff matrix, of shape (m, n).

    own_supp : ndarray(int, ndim=1)
        Array containing the player's action indices, of length k.

    opp_supp : ndarray(int, ndim=1)
        Array containing the opponent's action indices, of length k.

    A : ndarray(float, ndim=2)
        Array used in intermediate steps, of shape (k+1, k+1).

    out : ndarray(float, ndim=1)
        Array of length k+1 to store the k nonzero values of the desired
        mixed action in `out[:-1]` (and the payoff value in `out[-1]`).

    Returns
    -------
    bool
        `True` if a desired mixed action exists and `False` otherwise.

    """
    m = payoff_matrix.shape[0]
    k = len(own_supp)

    for i in range(k):
        for j in range(k):
            A[j, i] = payoff_matrix[own_supp[i], opp_supp[j]]  # transpose
    A[:-1, -1] = 1
    A[-1, :-1] = -1
    A[-1, -1] = 0
    out[:-1] = 0
    out[-1] = 1

    r = _numba_linalg_solve(A, out)
    if r != 0:  # A: singular
        return False
    for i in range(k):
        if out[i] <= 0:
            return False
    val = out[-1]

    if k == m:
        return True

    own_supp_flags = np.zeros(m, np.bool_)
    own_supp_flags[own_supp] = True

    for i in range(m):
        if not own_supp_flags[i]:
            payoff = 0
            for j in range(k):
                payoff += payoff_matrix[i, opp_supp[j]] * out[j]
            if payoff > val:
                return False
    return True